NMT has a complex way to account arena memory.
Arena memory is malloced. Arenas are tagged with a certain tag, e.g. mtCompiler.
When an Arena grows, a chunk is retrieved from the chunk pool. If no free chunk is in the pool, we malloc a new chunk (mtChunk). That increases the malloc counter `malloc[mtChunk]+=x`. We then also account the arena growth as `arena[mtCompiler]+=x`.
Therefore, the global `malloc[mtChunk]` malloc counter holds the number of bytes allocated for all chunks, in total. Some of these may be in use by arenas, some of these may be free in the pool. The various `arena[xxx]` counters hold the number of bytes allocated for that specific tag for arena.
When we report numbers, we also report total size of malloc and arena memory. For the individual tags, the arena memory counter and the malloc counters are disjunct. That means that chunks allocated for an arena on behalf of e.g. the C2 are tagged as mtChunk. The compiler memory only appears in the arena counters.
The reported total malloc size is the sum of all malloc counters. But we correct it by subtracting the mtChunk size.
It basically means that we account arena memory in its own, parallel, category that runs alongside "malloc". The current coding is unfortunately complicated though: We correct the total counters only on-the-fly when we generate a report (see `NMTUsage::update_malloc_usage()` and `MallocMemorySnapshot::make_adjustment()`, both are only executed on demand).
It also means that we need to synchronize the chunk malloc and the chunk arena accounting, to prevent the on-the-fly calculations from being wrong.
Other effects this has:
- for "Arena Chunk malloc", the number of allocations (#xxx)
- for "Arena Chunk malloc", the peak values are wrong
- in detail mode, by-callstack display of arena allocations are tagged as "Arena Chunk", not by the category the Arena belongs to, which would be a lot more useful.
There may be more things wrong, but those are the ones I spot. There also seems to be another bug, in that "Arena Chunks malloc" is never zero, even though there are no free chunk pools.
-----
We should think of ways to do this differently. In the opinion of the issue author, malloc counters should contain the full malloc load from hotspot, including arena memory. Thus, arena chunks should be accounted not towards an anonymous "mtChunk" category, but towards the tag the arena is tagged with, e.g. mtCompiler.
Then, in the NMT report, the meaning of arena and malloc numbers would slightly differ. Arena numbers would have to be understood as being a sub-part of the total malloc load for the same category.
As long as we still have chunk pools, we can retain the mtChunk category with a changed meaning: "free chunks not in use by any arena". This would be a lot more useful than today's use of that tag.
We also should investigate whether we even need the chunk pool. Removing the pool, although just tangential to this issue, would make matters a lot easier. See https://bugs.openjdk.org/browse/JDK-8333151.
Arena memory is malloced. Arenas are tagged with a certain tag, e.g. mtCompiler.
When an Arena grows, a chunk is retrieved from the chunk pool. If no free chunk is in the pool, we malloc a new chunk (mtChunk). That increases the malloc counter `malloc[mtChunk]+=x`. We then also account the arena growth as `arena[mtCompiler]+=x`.
Therefore, the global `malloc[mtChunk]` malloc counter holds the number of bytes allocated for all chunks, in total. Some of these may be in use by arenas, some of these may be free in the pool. The various `arena[xxx]` counters hold the number of bytes allocated for that specific tag for arena.
When we report numbers, we also report total size of malloc and arena memory. For the individual tags, the arena memory counter and the malloc counters are disjunct. That means that chunks allocated for an arena on behalf of e.g. the C2 are tagged as mtChunk. The compiler memory only appears in the arena counters.
The reported total malloc size is the sum of all malloc counters. But we correct it by subtracting the mtChunk size.
It basically means that we account arena memory in its own, parallel, category that runs alongside "malloc". The current coding is unfortunately complicated though: We correct the total counters only on-the-fly when we generate a report (see `NMTUsage::update_malloc_usage()` and `MallocMemorySnapshot::make_adjustment()`, both are only executed on demand).
It also means that we need to synchronize the chunk malloc and the chunk arena accounting, to prevent the on-the-fly calculations from being wrong.
Other effects this has:
- for "Arena Chunk malloc", the number of allocations (#xxx)
- for "Arena Chunk malloc", the peak values are wrong
- in detail mode, by-callstack display of arena allocations are tagged as "Arena Chunk", not by the category the Arena belongs to, which would be a lot more useful.
There may be more things wrong, but those are the ones I spot. There also seems to be another bug, in that "Arena Chunks malloc" is never zero, even though there are no free chunk pools.
-----
We should think of ways to do this differently. In the opinion of the issue author, malloc counters should contain the full malloc load from hotspot, including arena memory. Thus, arena chunks should be accounted not towards an anonymous "mtChunk" category, but towards the tag the arena is tagged with, e.g. mtCompiler.
Then, in the NMT report, the meaning of arena and malloc numbers would slightly differ. Arena numbers would have to be understood as being a sub-part of the total malloc load for the same category.
As long as we still have chunk pools, we can retain the mtChunk category with a changed meaning: "free chunks not in use by any arena". This would be a lot more useful than today's use of that tag.
We also should investigate whether we even need the chunk pool. Removing the pool, although just tangential to this issue, would make matters a lot easier. See https://bugs.openjdk.org/browse/JDK-8333151.
- relates to
-
JDK-8333151 Investigate if the Hotspot Arena chunk pools still make sense
- In Progress