JMH中allocation rate含义及GC Profiler内存测量结果解读求助
Hey there! Let's break this down step by step—first making sense of GC Profiler results, then clarifying what allocation rate means in JMH. I’ve been stuck on these exact questions before, so I get how frustrating it can be when metrics don’t feel intuitive.
GC Profiler outputs can feel overwhelming at first, but focusing on these key metrics will help you pinpoint actual memory usage:
- Heap Usage Peaks: Look for the maximum
used heapvalue before a garbage collection cycle runs. This is the highest amount of memory your benchmark consumed during that period. If you run the benchmark multiple times, averaging these peaks will give you a reliable measure of the typical memory footprint. - GC Cycle Details: Pay attention to the difference between pre-GC and post-GC used memory. For example:
Pre-GC: 800MB used; Post-GC: 200MB used
This means 600MB of temporary objects were cleaned up—your benchmark’s "steady state" memory usage is closer to that 200MB post-GC value, while the 800MB is the peak it reached between GCs. - Memory Pool Breakdown: Most profilers split the heap into young (Eden/Survivor) and old generations. If Eden fills up quickly and triggers frequent Minor GCs, your benchmark is creating lots of short-lived objects. If the old generation’s used memory keeps growing without being reclaimed, that’s a sign of long-lived objects accumulating (potentially a leak, though less likely in a controlled benchmark).
If you’re not seeing a direct "total memory consumed" number, just add up the used values across all memory pools (Eden + Survivor + Old Gen) at the peak point—that’s your actual memory usage for the benchmark.
Allocation rate in JMH is one of the most useful metrics for understanding your code’s memory efficiency:
It measures the total number of bytes allocated on the heap per second during your benchmark (shown as gc.alloc.rate with units like MB/sec). There’s also a normalized version, gc.alloc.rate.norm, which tells you how many bytes are allocated per individual benchmark operation (e.g., per method call).
Why does this matter?
- A high allocation rate means your code is creating tons of objects quickly—this will trigger more frequent Minor GCs, which add overhead to your runtime.
- A low allocation rate (especially the normalized one) indicates your code is minimizing unnecessary object creation (like avoiding temporary Strings, redundant wrapper classes, or short-lived collections).
- For example, if
gc.alloc.rate.normis 2048B, that means every time your benchmark method runs, it allocates ~2KB of new objects on the heap.
Pro tip: You can combine JMH and GC profiling directly by running your benchmark with the -prof gc flag. This will embed GC stats and allocation rates right into your JMH results, so you don’t have to parse separate GC logs.
内容的提问来源于stack exchange,提问作者Tri Nguyen




