Skip to content

Instantly share code, notes, and snippets.

@Scoppio
Created September 9, 2020 19:21
Show Gist options
  • Save Scoppio/a12a9301bec7ade44b191ea5c77b74bf to your computer and use it in GitHub Desktop.
Save Scoppio/a12a9301bec7ade44b191ea5c77b74bf to your computer and use it in GitHub Desktop.
Unbranched Max, thread-unsafe
package com.abstractobserver
import com.google.common.base.Stopwatch;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* This test object is to learn how to use Unsafe, its possibilities which are
* interesting for more complex and lower level programmin that usually arent
* possible with day-to-day programming.
*
* @author lucasscoppio
*/
public class UnbranchedTests {
public static final class UnbranchedMax {
private static final Unsafe unsafe;
private static final long valueOffset;
private static final long secondValueOffset;
private volatile int a = 0;
private volatile int b = 0;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
valueOffset = unsafe.objectFieldOffset
(UnbranchedMax.class.getDeclaredField("a"));
secondValueOffset = unsafe.objectFieldOffset
(UnbranchedMax.class.getDeclaredField("b"));
} catch (Exception ex) { throw new Error(ex); }
}
private UnbranchedMax() {}
private static final UnbranchedMax m = new UnbranchedMax();
public static int max(final int a, final int b) {
unsafe.putBoolean(m, valueOffset, a > b);
unsafe.putBoolean(m, secondValueOffset, b > a);
return a * m.a + b * m.b;
}
}
public static void main(String[] args) {
Random r = new Random();
int[] values = new int[10_0000];
for (int i = 0; i < 10_0000; i++) {
values[i] = r.nextInt();
}
Stopwatch st = Stopwatch.createStarted();
for (int i = 0; i < values.length -1; i++) {
UnbranchedMax.max(values[i], values[i+1]);
}
st.stop();
System.out.println(st);
System.out.println(st.elapsed(TimeUnit.NANOSECONDS) / 10_0000 + " ns per item");
// Final result in my machine shows it to be around 3 to 4 times slower than Math.max
// and almost 2 times slower than a simple `return a > b? a : b;`
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment