RFR: 7903572: JMH: mempool should capture Direct/Mapped memory pools as well
Alexey Vinogradov
duke at openjdk.org
Fri Oct 20 16:30:12 UTC 2023
On Wed, 11 Oct 2023 10:37:57 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:
> Can you post the sample output for this profiler?
Sure, consider this benchmark:
public class SegmentBenchmark {
@Warmup(iterations = 1)
@Measurement(iterations = 1)
@Benchmark
public void testMethod() {
final UUID unique = UUID.randomUUID();
final String fileName = unique.toString();
final File file = new File(String.format("/tmp/%s", fileName));
final Path filePath = file.toPath();
final MappedByteBuffer byteBuffer;
try {
try (final FileChannel fileChannel = FileChannel.open(filePath,
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE_NEW)) {
IoUtil.fill(fileChannel, 0, 1024 * 1024 * 32, (byte) 0);
byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 1024 * 1024 * 32);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
byteBuffer.put(0, (byte) 1);
byteBuffer.force();
IoUtil.unmap(byteBuffer);
try {
Files.deleteIfExists(filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws RunnerException {
final Options options = new OptionsBuilder()
.include(SegmentBenchmark.class.getSimpleName())
.forks(1)
.threads(10)
.addProfiler(MemPoolProfiler.class)
.shouldDoGC(true)
.build();
new Runner(options).run();
}
}
So, the output is:
# JMH version: 1.38-SNAPSHOT
# VM version: JDK 17.0.7, OpenJDK 64-Bit Server VM, 17.0.7+7
# VM invoker: /Users/aivinog1/.sdkman/candidates/java/17.0.7-tem/bin/java
# VM options: -javaagent:/Users/aivinog1/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar=58540:/Users/aivinog1/Applications/IntelliJ IDEA Ultimate.app/Contents/bin -Dfile.encoding=UTF-8
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 1 iterations, 10 s each
# Measurement: 1 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 10 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.aivinog1.SegmentBenchmark.testMethod
# Run progress: 0,00% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration 1: 14,484 ops/s
Iteration 1: 14,127 ops/s
mempool.CodeHeap 'non-nmethods'.used: 1138,750 KiB
mempool.CodeHeap 'non-profiled nmethods'.used: 352,500 KiB
mempool.CodeHeap 'profiled nmethods'.used: 1671,250 KiB
mempool.Compressed Class Space.used: 1079,234 KiB
mempool.G1 Eden Space.used: ≈ 0 KiB
mempool.G1 Old Gen.used: 3978,289 KiB
mempool.G1 Survivor Space.used: ≈ 0 KiB
mempool.Metaspace.used: 11299,758 KiB
mempool.direct.used: 112,000 KiB
mempool.mapped - 'non-volatile memory'.used: ≈ 0 KiB
mempool.mapped.used: ≈ 0 KiB
mempool.total.codeheap.used: 3162,500 KiB
mempool.total.used: 19631,781 KiB
Result "org.aivinog1.SegmentBenchmark.testMethod":
14,127 ops/s
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'non-nmethods'.used":
1138,750 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'non-profiled nmethods'.used":
352,500 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'profiled nmethods'.used":
1671,250 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.Compressed Class Space.used":
1079,234 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Eden Space.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Old Gen.used":
3978,289 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Survivor Space.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.Metaspace.used":
11299,758 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.direct.used":
112,000 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.mapped - 'non-volatile memory'.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.mapped.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.total.codeheap.used":
3162,500 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.total.used":
19631,781 KiB
# Run complete. Total time: 00:00:24
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.
NOTE: Current JVM experimentally supports Compiler Blackholes, and they are in use. Please exercise
extra caution when trusting the results, look into the generated code to check the benchmark still
works, and factor in a small probability of new VM bugs. Additionally, while comparisons between
different JVMs are already problematic, the performance difference caused by different Blackhole
modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons.
Benchmark Mode Cnt Score Error Units
SegmentBenchmark.testMethod thrpt 14,127 ops/s
SegmentBenchmark.testMethod:mempool.CodeHeap 'non-nmethods'.used thrpt 1138,750 KiB
SegmentBenchmark.testMethod:mempool.CodeHeap 'non-profiled nmethods'.used thrpt 352,500 KiB
SegmentBenchmark.testMethod:mempool.CodeHeap 'profiled nmethods'.used thrpt 1671,250 KiB
SegmentBenchmark.testMethod:mempool.Compressed Class Space.used thrpt 1079,234 KiB
SegmentBenchmark.testMethod:mempool.G1 Eden Space.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.G1 Old Gen.used thrpt 3978,289 KiB
SegmentBenchmark.testMethod:mempool.G1 Survivor Space.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.Metaspace.used thrpt 11299,758 KiB
SegmentBenchmark.testMethod:mempool.direct.used thrpt 112,000 KiB
SegmentBenchmark.testMethod:mempool.mapped - 'non-volatile memory'.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.mapped.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.total.codeheap.used thrpt 3162,500 KiB
SegmentBenchmark.testMethod:mempool.total.used thrpt 19631,781 KiB
If we want to check the `mapped` part (just drop `IoUtil.unmap(byteBuffer);`), the output will be:
# JMH version: 1.38-SNAPSHOT
# VM version: JDK 17.0.7, OpenJDK 64-Bit Server VM, 17.0.7+7
# VM invoker: /Users/aivinog1/.sdkman/candidates/java/17.0.7-tem/bin/java
# VM options: -javaagent:/Users/aivinog1/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar=58614:/Users/aivinog1/Applications/IntelliJ IDEA Ultimate.app/Contents/bin -Dfile.encoding=UTF-8
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 1 iterations, 10 s each
# Measurement: 1 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 10 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.aivinog1.SegmentBenchmark.testMethod
# Run progress: 0,00% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration 1: 16,045 ops/s
Iteration 1: 15,994 ops/s
mempool.CodeHeap 'non-nmethods'.used: 1153,750 KiB
mempool.CodeHeap 'non-profiled nmethods'.used: 354,500 KiB
mempool.CodeHeap 'profiled nmethods'.used: 1665,125 KiB
mempool.Compressed Class Space.used: 1072,508 KiB
mempool.G1 Eden Space.used: ≈ 0 KiB
mempool.G1 Old Gen.used: 3989,570 KiB
mempool.G1 Survivor Space.used: ≈ 0 KiB
mempool.Metaspace.used: 11262,086 KiB
mempool.direct.used: 112,000 KiB
mempool.mapped - 'non-volatile memory'.used: ≈ 0 KiB
mempool.mapped.used: 5668864,000 KiB
mempool.total.codeheap.used: 3173,375 KiB
mempool.total.used: 5688473,539 KiB
Result "org.aivinog1.SegmentBenchmark.testMethod":
15,994 ops/s
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'non-nmethods'.used":
1153,750 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'non-profiled nmethods'.used":
354,500 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.CodeHeap 'profiled nmethods'.used":
1665,125 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.Compressed Class Space.used":
1072,508 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Eden Space.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Old Gen.used":
3989,570 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.G1 Survivor Space.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.Metaspace.used":
11262,086 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.direct.used":
112,000 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.mapped - 'non-volatile memory'.used":
≈ 0 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.mapped.used":
5668864,000 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.total.codeheap.used":
3173,375 KiB
Secondary result "org.aivinog1.SegmentBenchmark.testMethod:mempool.total.used":
5688473,539 KiB
# Run complete. Total time: 00:00:23
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.
NOTE: Current JVM experimentally supports Compiler Blackholes, and they are in use. Please exercise
extra caution when trusting the results, look into the generated code to check the benchmark still
works, and factor in a small probability of new VM bugs. Additionally, while comparisons between
different JVMs are already problematic, the performance difference caused by different Blackhole
modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons.
Benchmark Mode Cnt Score Error Units
SegmentBenchmark.testMethod thrpt 15,994 ops/s
SegmentBenchmark.testMethod:mempool.CodeHeap 'non-nmethods'.used thrpt 1153,750 KiB
SegmentBenchmark.testMethod:mempool.CodeHeap 'non-profiled nmethods'.used thrpt 354,500 KiB
SegmentBenchmark.testMethod:mempool.CodeHeap 'profiled nmethods'.used thrpt 1665,125 KiB
SegmentBenchmark.testMethod:mempool.Compressed Class Space.used thrpt 1072,508 KiB
SegmentBenchmark.testMethod:mempool.G1 Eden Space.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.G1 Old Gen.used thrpt 3989,570 KiB
SegmentBenchmark.testMethod:mempool.G1 Survivor Space.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.Metaspace.used thrpt 11262,086 KiB
SegmentBenchmark.testMethod:mempool.direct.used thrpt 112,000 KiB
SegmentBenchmark.testMethod:mempool.mapped - 'non-volatile memory'.used thrpt ≈ 0 KiB
SegmentBenchmark.testMethod:mempool.mapped.used thrpt 5668864,000 KiB
SegmentBenchmark.testMethod:mempool.total.codeheap.used thrpt 3173,375 KiB
SegmentBenchmark.testMethod:mempool.total.used thrpt 5688473,539 KiB
> jmh-core/src/main/java/org/openjdk/jmh/profile/MemPoolProfiler.java line 72:
>
>> 70: final long used = bean.getMemoryUsed();
>> 71: sum += used;
>> 72: results.add(new ScalarResult(String.format("mempool.%s.used", bean.getName()), used / BYTES_PER_KIB, "KiB", AggregationPolicy.MAX));
>
> Please match the style of the for-loop above:
> - drop `final` from `used`;
> - use regular concat instead of String.format;
Done
> jmh-core/src/main/java/org/openjdk/jmh/profile/MemPoolProfiler.java line 74:
>
>> 72: results.add(new ScalarResult("mempool.total.used", sum / BYTES_PER_KIB, "KiB", AggregationPolicy.MAX));
>> 73:
>> 74: results.addAll(
>
> These need to be added to `mempool.total.used`. Also, rewrite it in the same style as existing code, without streams.
Thanks, done
> jmh-core/src/main/java/org/openjdk/jmh/profile/MemPoolProfiler.java line 77:
>
>> 75: results.add(new ScalarResult("mempool.total.codeheap.used", sumCodeHeap / BYTES_PER_KIB, "KiB", AggregationPolicy.MAX));
>> 76: results.add(new ScalarResult("mempool.total.used", sum / BYTES_PER_KIB, "KiB", AggregationPolicy.MAX));
>> 77:
>
> No newline is needed here.
Done
-------------
PR Comment: https://git.openjdk.org/jmh/pull/124#issuecomment-1757413528
PR Review Comment: https://git.openjdk.org/jmh/pull/124#discussion_r1354639306
PR Review Comment: https://git.openjdk.org/jmh/pull/124#discussion_r1354629905
PR Review Comment: https://git.openjdk.org/jmh/pull/124#discussion_r1354638957
More information about the jmh-dev
mailing list