しつこく 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); } } }