blob: af9ab9d05d179f639997ce80941d0005742a1115 [file] [log] [blame]
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* Micro-benchmark that can be used to see if use of {@link sun.misc.Unsafe}
* might allow speeding up serialization and deserialization.
*
* @author tatu
*/
public class TestUnsafePerf
{
final static class Bean {
public String name;
public long id;
public int count;
public boolean enabled;
}
private final int REPS = 90000;
private final Unsafe unsafe;
private final long offsetName;
private final long offsetId;
private final long offsetCount;
private final long offsetEnabled;
private Field fieldName;
private Field fieldId;
private Field fieldCount;
private Field fieldEnabled;
private Field fastFieldName;
private Field fastFieldId;
private Field fastFieldCount;
private Field fastFieldEnabled;
private final static String VALUE_NAME = "foobar";
private final static long VALUE_ID = 123456L;
private final static int VALUE_COUNT = 17;
public TestUnsafePerf() throws Exception
{
// First: access "unsafe" to test
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = (Unsafe) unsafeField.get(null);
Class<?> cls = Bean.class;
fieldName = cls.getDeclaredField("name");
fastFieldName = cls.getDeclaredField("name");
fastFieldName.setAccessible(true);
offsetName = unsafe.objectFieldOffset(fieldName);
fieldId = cls.getDeclaredField("id");
fastFieldId = cls.getDeclaredField("id");
fastFieldId.setAccessible(true);
offsetId = unsafe.objectFieldOffset(fieldId);
fieldCount = cls.getDeclaredField("count");
fastFieldCount = cls.getDeclaredField("count");
fastFieldCount.setAccessible(true);
offsetCount = unsafe.objectFieldOffset(fieldCount);
fieldEnabled = cls.getDeclaredField("enabled");
fastFieldEnabled = cls.getDeclaredField("enabled");
fastFieldEnabled.setAccessible(true);
offsetEnabled = unsafe.objectFieldOffset(fieldEnabled);
}
public void test()
throws Exception
{
int i = 0;
int sum = 0;
while (true) {
try { Thread.sleep(100L); } catch (InterruptedException ie) { }
int round = (i++ % 4);
long curr = System.currentTimeMillis();
String msg;
boolean lf = (round == 0);
switch (round) {
case 0:
msg = "Reflection/fast";
sum += testReflectionFast(REPS);
break;
case 1:
msg = "Unsafe";
sum += testUnsafe(REPS);
break;
case 2:
msg = "Regular/direct";
sum += testRegular(REPS);
break;
case 3:
msg = "Reflection/slow";
sum += testReflectionSlow(REPS);
break;
default:
throw new Error("Internal error");
}
curr = System.currentTimeMillis() - curr;
if (lf) {
System.out.println();
}
System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(sum & 0xFF)+").");
}
}
protected int testReflectionSlow(int reps) throws Exception
{
Bean ob = new Bean();
for (int i = 0; i < reps; ++i) {
fieldName.set(ob, VALUE_NAME);
fieldId.set(ob, Long.valueOf(VALUE_ID));
fieldCount.set(ob, Integer.valueOf(VALUE_COUNT));
fieldEnabled.set(ob, Boolean.TRUE);
}
return ob.hashCode(); // just to get some non-optimizable number
}
protected int testReflectionFast(int reps) throws Exception
{
Bean ob = new Bean();
for (int i = 0; i < reps; ++i) {
fastFieldName.set(ob, VALUE_NAME);
/*
fastFieldId.set(ob, Long.valueOf(VALUE_ID));
fastFieldCount.set(ob, Integer.valueOf(VALUE_COUNT));
fastFieldEnabled.set(ob, Boolean.TRUE);
*/
fastFieldId.setLong(ob, VALUE_ID);
fastFieldCount.setInt(ob, VALUE_COUNT);
fastFieldEnabled.setBoolean(ob, true);
}
return ob.hashCode(); // just to get some non-optimizable number
}
protected int testUnsafe(int reps) throws Exception
{
Bean ob = new Bean();
for (int i = 0; i < reps; ++i) {
unsafe.putObject(ob, offsetName, VALUE_NAME);
unsafe.putLong(ob, offsetId, VALUE_ID);
unsafe.putInt(ob, offsetCount, VALUE_COUNT);
unsafe.putBoolean(ob, offsetEnabled, true);
}
return ob.hashCode(); // just to get some non-optimizable number
}
protected int testRegular(int reps) throws Exception
{
Bean ob = new Bean();
for (int i = 0; i < reps; ++i) {
ob.name = VALUE_NAME;
ob.id = VALUE_ID;
ob.count = VALUE_COUNT;
ob.enabled = true;
}
return ob.hashCode(); // just to get some non-optimizable number
}
public static void main(String[] args)
throws Exception
{
new TestUnsafePerf().test();
}
}