直接java.nio.ByteBufferの読み取りパフォーマンスをテストしていたとき、私は絶対読み取りが相対読み取りよりも平均2倍速いことに気付きました。また、相対読み取りと絶対読み取りのソースコードを比較すると、相対読み取りと内部カウンタを除いてコードはほとんど同じです。なぜ私はスピードのこのような大きな違いを見ますか?以下は Direct ByteBuffer relativeと絶対読み取りパフォーマンス
は私のJMHベンチマークのソースコードです:public class DirectByteBufferReadBenchmark {
private static final int OBJ_SIZE = 8 + 4 + 1;
private static final int NUM_ELEM = 10_000_000;
@State(Scope.Benchmark)
public static class Data {
private ByteBuffer directByteBuffer;
@Setup
public void setup() {
directByteBuffer = ByteBuffer.allocateDirect(OBJ_SIZE * NUM_ELEM);
for (int i = 0; i < NUM_ELEM; i++) {
directByteBuffer.putLong(i);
directByteBuffer.putInt(i);
directByteBuffer.put((byte) (i & 1));
}
}
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public long testReadAbsolute(Data d) throws InterruptedException {
long val = 0l;
for (int i = 0; i < NUM_ELEM; i++) {
int index = OBJ_SIZE * i;
val += d.directByteBuffer.getLong(index);
d.directByteBuffer.getInt(index + 8);
d.directByteBuffer.get(index + 12);
}
return val;
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public long testReadRelative(Data d) throws InterruptedException {
d.directByteBuffer.rewind();
long val = 0l;
for (int i = 0; i < NUM_ELEM; i++) {
val += d.directByteBuffer.getLong();
d.directByteBuffer.getInt();
d.directByteBuffer.get();
}
return val;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(DirectByteBufferReadBenchmark.class.getSimpleName())
.warmupIterations(5)
.measurementIterations(5)
.forks(3)
.threads(1)
.build();
new Runner(opt).run();
}
}
そして、これらは私のベンチマークの実行の結果である:テストはMacbookPro(2.2GHzのインテルCore上で実行された
Benchmark Mode Cnt Score Error Units
DirectByteBufferReadBenchmark.testReadAbsolute thrpt 15 88.605 ± 9.276 ops/s
DirectByteBufferReadBenchmark.testReadRelative thrpt 15 42.904 ± 3.018 ops/s
i7,16Gb DDR3)およびJDK 1.8.0_73をサポートしています。
UPDATE
私はJDK 9-EA B134と同じテストを実行します。どちらのテストも約10%のスピードアップを示していますが、2つのスピードの差は似ています。
# JMH 1.13 (released 45 days ago)
# VM version: JDK 9-ea, VM 9-ea+134
# VM invoker: /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
# VM options: <none>
Benchmark Mode Cnt Score Error Units
DirectByteBufferReadBenchmark.testReadAbsolute thrpt 15 102.170 ± 10.199 ops/s
DirectByteBufferReadBenchmark.testReadRelative thrpt 15 45.988 ± 3.896 ops/s
ご回答ありがとうございます。私はJDK 9でテストしましたが、問題のアップデートを見ていますが、相対的な読み込みがはるかに優れているとは思いません。なぜどんなアイデア? –
@VladimirG。はい、私のベンチマークは本当に少し異なっていました。私は答えを更新しました。理由は同じです.JITは 'position'フィールドの更新を最適化しません。そのため、相対ByteBufferアクセスは効率が悪いようです。 – apangin