RFR: JDK-8255884: Metaspace: chunk local commit counter may be stale [v4]
Thomas Stuefe
stuefe at openjdk.java.net
Thu Dec 17 06:12:25 UTC 2020
> The detailed metaspace report (`jcmd VM.metaspace`) shows the ChunkManager statistics. In these statistics, the commit counter for chunk levels < granule size may be wrong.
>
> Note that this is not a big deal. It does not affect the total commit counter, which is directly taken from the virtual memory layer, and which is always right. But it can be confusing for analysts.
>
> Background:
>
> The "truth" about the commit state of granules is kept inside VirtualSpaceNode in a bitmask ("commit mask"). Since this is a global resource and access to it is synchronized, each chunk keeps a commit watermark to know the size of the range which is guaranteed to be committed and which can be used without checking that bitmap. This watermark is checked when allocating from the chunk.
>
> This chunk-local watermark can get stale if the granule underneath the chunk gets committed without the chunk noticing. The only way this can happen is if the chunk is smaller than a granule and some in-granule neighbor was committed.
>
> That in itself works as designed and is totally benign. The chunk-local commit watermark will get silently corrected on the next allocation.
>
> But it messes up statistics a bit. Example:
>
> jcmd xxx VM.metaspace
>
> <snip>
>
> Chunk freelists:
> <snip>
> Both:
>
> 4m: (none)
> 2m: 2, capacity=4,00 MB, committed=0 bytes ( 0%)
> 1m: 1, capacity=1,00 MB, committed=0 bytes ( 0%)
> 512k: (none)
> 256k: 2, capacity=512,00 KB, committed=0 bytes ( 0%)
> 128k: 1, capacity=128,00 KB, committed=0 bytes ( 0%)
> 64k: 2, capacity=128,00 KB, committed=0 bytes ( 0%)
> 32k: 2, capacity=64,00 KB, committed=0 bytes ( 0%) <<<<< actually, these are committed
> 16k: 1, capacity=16,00 KB, committed=0 bytes ( 0%) <<<<< these too
> 8k: (none)
> 4k: (none)
> 2k: (none)
> 1k: (none)
> Total word size: 5,83 MB, committed: 0 bytes ( 0%)
>
>
> In this example, the 32K and 16K chunks in the freelist had been committed as a side effect of comitting a neighboring chunk. Their watermarks are still at zero though and therefore they appear uncommitted here.
>
> The solution would be to - when a small chunk gets committed - adjust the watermarks of his in-granule neighbors. Then it looks like this:
>
> Both:
>
> 4m: (none)
> 2m: 3, capacity=6,00 MB, committed=0 bytes ( 0%)
> 1m: 2, capacity=2,00 MB, committed=0 bytes ( 0%)
> 512k: 1, capacity=512,00 KB, committed=0 bytes ( 0%)
> 256k: (none)
> 128k: 1, capacity=128,00 KB, committed=0 bytes ( 0%)
> 64k: 1, capacity=64,00 KB, committed=0 bytes ( 0%)
> 32k: 2, capacity=64,00 KB, committed=64,00 KB (100%) <<<<< good
> 16k: 2, capacity=32,00 KB, committed=32,00 KB (100%) <<<<< good
> 8k: (none)
> 4k: (none)
> 2k: (none)
> 1k: (none)
> Total word size: 8,78 MB, committed: 96,00 KB ( 1%)
>
> Thanks, Thomas
Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision:
- Fix death test
- Merge
- Add an assert to make chunk-to-granule-geometry explicit
- Merge
- Add gtest for Vsn::is_range_fully_committed
- Initial
-------------
Changes:
- all: https://git.openjdk.java.net/jdk/pull/1291/files
- new: https://git.openjdk.java.net/jdk/pull/1291/files/205425e8..901d42ba
Webrevs:
- full: https://webrevs.openjdk.java.net/?repo=jdk&pr=1291&range=03
- incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=1291&range=02-03
Stats: 68824 lines in 1566 files changed: 50262 ins; 11937 del; 6625 mod
Patch: https://git.openjdk.java.net/jdk/pull/1291.diff
Fetch: git fetch https://git.openjdk.java.net/jdk pull/1291/head:pull/1291
PR: https://git.openjdk.java.net/jdk/pull/1291
More information about the hotspot-runtime-dev
mailing list