2011年4月26日火曜日

ByteBufferの速度

ByteBufferはプリミティブな型の数値からbyte配列を簡単につくってくれる。
だけど、ByteBuffer.classの中身を見るとabstractとか使ってたりインスタンス生成したりするので意外とコストがかかる。
なので、自前でビットシフトを使って作ったメソッドを作ってみた。ByteBuffer.classの中身を追った感じは同じ用な考え方で実装してた。
速度を測ってみたら自前でつくったメソッドの方が早く動作した。

・Main.java
ByteBufferと自前でビットシフトをするメソッドで1000000回変換した場合の時間を測定

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {

        final int LOOP = 1000000;
        final int value = 0x12345678;

        ByteBuffer buf = ByteBuffer.allocate(16);
        buf.order(ByteOrder.LITTLE_ENDIAN);
        byte[] dat = new byte[16];

        long s_time = System.nanoTime();

        for (int i = 0; i < LOOP; i++) {
            DataConverter.setValue(dat, 0, value);
            DataConverter.setValue(dat, 3, value);
            DataConverter.setValue(dat, 7, value);
            DataConverter.setValue(dat, 11, value);
        }

        System.out.println("Convertor:" + (System.nanoTime() - s_time) / LOOP);

        for (int i = 0; i < dat.length; i++) {
            System.out.format("%02X ", dat[i]);
        }
        System.out.println();
        System.out.println();

        s_time = System.nanoTime();

        for (int i = 0; i < LOOP; i++) {
            buf.putInt(0, value);
            buf.putInt(3, value);
            buf.putInt(7, value);
            buf.putInt(11, value);
            // byte[] d = buf.array();
        }
        System.out.println("ByteBuffer:" + (System.nanoTime() - s_time) / LOOP);

        byte[] d = buf.array();
        for (int i = 0; i < d.length; i++) {
            System.out.format("%02X ", d[i]);
        }

    }
}
・DataConvertor.java
public final class DataConverter {

    /** int型のバイトサイズ */
    private static final int SIZE_INTEGER = Integer.SIZE / Byte.SIZE;

    /** マスク */
    private static final int MASK = 0xFF;

    public static void setValue(final byte[] dest, final int offset, final int src) {
        for (int i = 0; i < SIZE_INTEGER; i++) {
            dest[offset + i] = (byte)(src >> Byte.SIZE * i & MASK);
        }
    }
}
●結果
Convertor:56
78 56 34 78 56 34 12 78 56 34 12 78 56 34 12 00

ByteBuffer:130
78 56 34 78 56 34 12 78 56 34 12 78 56 34 12 00
どちらも出力の形は一緒になったけど、時間に差が出た。 10回やってみた結果。
cnt = 1
Convertor :  54ns
ByteBuffer: 139ns
cnt = 2
Convertor :  53ns
ByteBuffer: 130ns
cnt = 3
Convertor :  49ns
ByteBuffer: 131ns
cnt = 4
Convertor :  50ns
ByteBuffer: 134ns
cnt = 5
Convertor :  50ns
ByteBuffer: 129ns
cnt = 6
Convertor :  50ns
ByteBuffer: 130ns
cnt = 7
Convertor :  52ns
ByteBuffer: 131ns
cnt = 8
Convertor :  50ns
ByteBuffer: 127ns
cnt = 9
Convertor :  50ns
ByteBuffer: 131ns
cnt = 10
Convertor :  50ns
ByteBuffer: 131ns