しつこく unsafe

配列アクセス on Mac PPC。環境によって優劣は変わるようです。P@U では殆ど差が出ない様子。

$ java Test
Normal: 3992299000
Trick:  3663968000
Flat:   3079973000
import java.util.*;
import java.lang.reflect.*;
import sun.misc.*;

class Test
{
    static final int LENGTH = 10000, LOOP = 10000;
    
    public static void main(String[] args) throws Exception
    {
        long t1, t2, t3;
        stabilize(); t1 = t(); normal(); t1 = t() - t1;
        stabilize(); t2 = t(); trick();  t2 = t() - t2;
        stabilize(); t3 = t(); flat();   t3 = t() - t3;
        System.out.println("Normal: " + t1);
        System.out.println("Trick:  " + t2);
        System.out.println("Flat:   " + t3);
    }
    private static long t()
    {
        return System.nanoTime();
    }
    private static void stabilize()
    {
        for (long t = t(); t() < t + 1e9; ) {
            int[] array = new int[LENGTH];
        }
        System.gc();
        for (long t = t(); t() < t + 1e9; ) ;
    }
    private static void normal()
    {
        // ふつう版
        for (int i = LOOP; --i >= 0; ) {
            int[] array = new int[LENGTH];
            for (int j = LENGTH; --j >= 0; )
                array[j] = j;
            for (int j = LENGTH; --j >= 0; )
                array[j]++;
        }
    }
    private static void trick() throws Exception
    {
        // 配列にダイレクトアクセス版(処理系依存、32bit only)
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe us = (Unsafe)f.get(null);
        long base = us.arrayBaseOffset(int[].class);
        for (int i = LOOP; --i >= 0; ) {
            int[] array = new int[LENGTH];
            us.putObject(array, base, array);
            long addr = us.getInt(array, base) + base;
            for (int j = LENGTH; --j >= 0; )
                us.putInt(addr + (j << 2), j);
            for (int j = LENGTH; --j >= 0; )
                us.putInt(addr + (j << 2), us.getInt(addr + (j << 2)) + 1);
        }
    }
    private static void flat() throws Exception
    {
        // そもそも配列じゃない版
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe us = (Unsafe)f.get(null);
        for (int i = LOOP; --i >= 0; ) {
            long array = us.allocateMemory(LENGTH << 2);
            for (int j = LENGTH; --j >= 0; )
                us.putInt(array + (j << 2), j);
            for (int j = LENGTH; --j >= 0; )
                us.putInt(array + (j << 2), us.getInt(array + (j << 2)) + 1);
            us.freeMemory(array);
        }
    }
}