Trong khi tôi đang thử nghiệm hiệu suất đọc của java.nio.ByteBuffer trực tiếp, tôi nhận thấy rằng giá trị đọc tuyệt đối trung bình gấp 2 lần so với đọc tương đối. Ngoài ra nếu tôi so sánh mã nguồn của tương đối so với đọc tuyệt đối, mã là khá nhiều giống nhau ngoại trừ việc đọc tương đối duy trì và truy cập nội bộ. Tôi tự hỏi tại sao tôi lại thấy sự khác biệt đáng kể về tốc độ?Trực tiếp ByteBuffer tương đối so với hiệu năng đọc tuyệt đối
Dưới đây là mã nguồn của JMH benchmark của tôi:
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();
}
}
Và đây là kết quả của chạy benchmark của tôi:
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
thử nghiệm được chạy trên một MacbookPro (2.2GHz Intel Core i7, 16Gb DDR3) và JDK 1.8.0_73.
CẬP NHẬT
tôi chạy thử nghiệm cùng với JDK b134 9-ea. Cả hai thử nghiệm cho thấy một tăng tốc độ 10% nhưng sự khác biệt tốc độ giữa hai vẫn tương tự.
# 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
cảm ơn câu trả lời của bạn. Tôi đã thử nghiệm với JDK 9, xem cập nhật trong câu hỏi, tuy nhiên tôi không thấy người đọc tương đối để thực hiện tốt hơn nhiều. Bất kỳ ý tưởng tại sao? –
@VladimirG. Vâng, điểm chuẩn của tôi thực sự hơi khác một chút. Tôi đã cập nhật câu trả lời. Lý do vẫn giống nhau: JIT không tối ưu hóa các cập nhật của trường 'position', đó là lý do tại sao việc truy cập ByteBuffer tương đối dường như kém hiệu quả hơn. – apangin