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