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();
    }
}
