0

AMFでは29ビット整数が一般的であるため、既知の最速/最高のルーチンを組み込みたいと思います。現在、2つのルーチンがライブラリに存在し、ideoneでライブテストできます。http
//ideone.com/KNmYT クイックリファレンスのソースは 次のとおりです。

public static int readMediumInt(ByteBuffer in) {
    ByteBuffer buf = ByteBuffer.allocate(4);
    buf.put((byte) 0x00);
    buf.put(in.get());
    buf.put(in.get());
    buf.put(in.get());
    buf.flip();
    return buf.getInt();
}

public static int readMediumInt2(ByteBuffer in) { byte[] bytes = new byte[3]; in.get(bytes); int val = 0; val += bytes[0] * 256 * 256; val += bytes[1] * 256; val += bytes[2]; if (val < 0) { val += 256; } return val; }

4

3 に答える 3

2

通常、これはビット演算で行います。2番目のバージョンは、最終的にJVMによってこれに近いものに最適化される可能性がありますが、確信が持てません。さて、これはあなたのサンプルに続く24ビットだけですが、質問は「29ビット整数」と言います。どちらが本当に欲しかったのかわかりません。

public static int readMediumInt(ByteBuffer buf) {
  return ((buf.get() & 0xFF) << 16) 
       | ((buf.get() & 0xFF) <<  8)
       | ((buf.get() & 0xFF);
}
于 2010-09-08T17:25:44.147 に答える
2

実際にAMF29ビット整数を読み取りたい場合は、これでうまくいくはずです(フォーマットを正しく理解していると仮定します)。

private static int readMediumInt(ByteBuffer buf) {
    int b0, b1, b2;
    if ((b0 = buf.get()) >= 0) return b0;
    if ((b1 = buf.get()) >= 0) return ((b0 << 7) & ((~(-1 << 7)) << 7)) | b1;
    if ((b2 = buf.get()) >= 0) return ((b0 << 14) & ((~(-1 << 7)) << 14)) | ((b1 << 7) & ((~(-1 << 7)) << 7)) | b2;
    return ((b0 << 22) & ((~(-1 << 7)) << 22)) | ((b1 << 15) & ((~(-1 << 7)) << 15)) | ((b2 << 8) & ((~(-1 << 7)) << 8)) | (buf.get() & 0xff);
}
于 2010-09-08T18:05:29.563 に答える
1

最も重要な変更は、メソッド内でオブジェクトを割り当てないようにすることです。ちなみに、マイクロベンチマークは「開始」をリセットしなかったため、2番目の結果には最初の方法に使用された時間が含まれます。また、マイクロベンチマークを複数回実行する必要があります。そうしないと、ジャストインタイムコンパイラが実行されません。次のような方法を使用することをお勧めします

public static int readMediumInt3(ByteBuffer buf) {
    return ((buf.get() & 0xff) << 16) + 
            ((buf.get() & 0xff) << 8) + 
            ((buf.get() & 0xff));
}

完全なコードは次のとおりです。

import java.nio.ByteBuffer;

public class Main {

    public static int readMediumInt(ByteBuffer in) {
        ByteBuffer buf = ByteBuffer.allocate(4);
        buf.put((byte) 0x00);
        buf.put(in.get());
        buf.put(in.get());
        buf.put(in.get());
        buf.flip();
        return buf.getInt();
    }

    public static int readMediumInt2(ByteBuffer in) {
        byte[] bytes = new byte[3];
        in.get(bytes);
        int val = 0;
        val += bytes[0] * 256 * 256;
        val += bytes[1] * 256;
        val += bytes[2];
        if (val < 0) {
            val += 256;
        }
        return val;
    }

    public static int readMediumInt3(ByteBuffer buf) {
        return ((buf.get() & 0xff) << 16) + 
                ((buf.get() & 0xff) << 8) + 
                ((buf.get() & 0xff));
    }

    public static void main(String[] args) {
        Main m = new Main();
        for (int i = 0; i < 5; i++) {
            // version 1
            ByteBuffer buf = ByteBuffer.allocate(4);
            buf.putInt(424242);
            buf.flip();
            long start;
            start = System.nanoTime();
            for (int j = 0; j < 10000000; j++) {
                buf.position(0);
                readMediumInt(buf);
            }
            start = System.nanoTime() - start;
            System.out.printf("Ver 1: elapsed: %d ms\n", start / 1000000);

            // version 2
            ByteBuffer buf2 = ByteBuffer.allocate(4);
            buf2.putInt(424242);
            buf2.flip();
            start = System.nanoTime();
            for (int j = 0; j < 10000000; j++) {
                buf2.position(0);
                readMediumInt2(buf2);
            }
            start = System.nanoTime() - start;
            System.out.printf("Ver 2: elapsed: %d ms\n", start / 1000000);

            // version 3
            ByteBuffer buf3 = ByteBuffer.allocate(4);
            buf3.putInt(424242);
            buf3.flip();
            start = System.nanoTime();
            for (int j = 0; j < 10000000; j++) {
                buf3.position(0);
                readMediumInt3(buf3);
            }
            start = System.nanoTime() - start;
            System.out.printf("Ver 3: elapsed: %d ms\n", start / 1000000);
        }

    }
}

私の結果:

  • Ver 1:経過:556ミリ秒
  • Ver 2:経過:187ミリ秒
  • Ver 3:経過:3ミリ秒
于 2010-09-08T18:39:24.677 に答える