[GR-18214] Compacting garbage collection (non-default).
@peter-hofer , I found the master thesis^0 for this commit, but the measurements are quite thin. Did you run internal measurements?
^0 https://epub.jku.at/obvulihs/download/pdf/9649056?originalFilename=true
@SergejIsbrecht, yes, and the gist of it is that it is somewhat comparable to the current copying GC, sometimes better and sometimes worse, both in terms of CPU usage and memory usage. We avoided adding a forwarding pointer to every object and instead store the new object locations in the gaps between sequences of live objects, which requires extra passes over the heap and more complex lookups for determining an object's new location and updating references to it. This in turn can make full collections more expensive, which can cause the GC policy to use more memory to do fewer collections. On the other hand, you get an (almost) hard heap size limit by collecting in-place. This initial implementation also isn't heavily tuned, so I believe there's still some low-hanging fruits to harvest.
@peter-hofer Thanks for this work and the presentation last week during the native image meeting. I'm giving this a go and wondering that the following native image build line should indicate whether mark-copy or mark-compact is in use:
Garbage collector: Serial GC (max heap size: 80% of RAM)
As it stands, there's no indication of which old gen algorithm is in use.
@galderz, thanks for giving it a try. In this branch, the CompactingOldGen option is on by default, but it won't be for merging. I believe that when it gets enabled explicitly, it will show up in the builder output as a custom option. Indicating it in the GC line is a possibility though.
@peter-hofer Thanks. I would also add some information to the log so that when -XX:+PrintGC is enabled, you see a message right away (even before GC has kicked in) on what GC parameters you are using at runtime.
Related to this, if you are tweaking the GC policy, the one used at runtime is only -XX:+VerboseGC is passed in which is very verbose. I think that the GC policy should also be logged on startup -XX:+PrintGC is passed in.
So, when tackling the old gen configuration info reporting at runtime, you could also tackle the gc policy configuration reporting.
To be more precise about GC policy, I'm tackling about this messages:
[7.525s] GC(0) Using Serial GC
[7.525s] GC(0) Memory: 32049M
[7.525s] GC(0) Heap policy: adaptive
[7.525s] GC(0) Maximum young generation size: 21M
[7.525s] GC(0) Maximum heap size: 64M
[7.525s] GC(0) Minimum heap size: 16M
[7.525s] GC(0) Aligned chunk size: 512K
[7.525s] GC(0) Large array threshold: 128K
These only appear when VerboseGC is on, and the only come up when GC kicks in, say when you start sending HTTP requests. PrintGC should be enough to see this and they should appear as soon as the native image starts, before any GC cycles kick in.
@peter-hofer I ran some quick tests locally with a basic Quarkus app and didn't see any major failures with it. Throughput seems to be about the same than the copying one, but latency at high percentiles shows ~10% worse. This can be understandable since as you said, the impl has not yet been optimized. I will be exploring additional angles in an upcoming blog post.