RFR: 8363932: G1: Better distribute KlassCleaningTask
Thomas Schatzl
tschatzl at openjdk.org
Wed Sep 17 14:03:58 UTC 2025
Hi all,
please review this change to parallel klass cleaning to improve performance.
The current implementation only parallelizes cleaning of weak class links, while the main work, cleaning the object tree is single-threaded. Hence in practice, the current mechanism does not scale beyond 2-3 threads.
Cleaning an object graph in an application that loads some jars and instantiates central classes within them, with around 180k classes the current `G1 Complete Cleaning` task (which executes this code) can take 80ms (with 25 threads).
The suggested change is to walk the object graph by (live) `ClassLoaderData` klass by klass, fixing only the links of that particular klass.
E.g.
CLD1 has klasses A, B, C, CLD2 has klasses a, b, c and CLD3 has klasses 0, 1, 2, 4;
vertical links are subklass references, while horizontal links are sibling references.
j.l.O
|
A - B - c - 3
|
0 - 2 - C - 1
CLD 3 is dead. Thread 1 claims CLD 1, Thread 2 claims CLD 2 (and nobody claims CLD3 because it's dead).
So thread 1, when reaching `A` fixes its subklass link to `C`, and otherwise does nothing with `A`. When looking at `C`, it will remove the link to `1`.
Thread 2 will only remove the link to `3` of `c`.
The result is
j.l.O
|
A - B - c
|
C
There should be no unnecessary object graph walking.
There is a slight change in printing during unlinking: previously the code, when cleaning subklasses it printed `unlinking class (subclass)`for every class that has been removed on the way to the next live one. In above case, it would print
unlinking class (subclass): 0
unlinking class (subclass): 2
With the change, to avoid following the subklasses of the graph twice, it prints
unlinking class (subclass): 0
unlinking class (sibling): 0
because the string in brackets is the actual link that is followed. I can revert that change.
With the change "Complete Cleaning" time for 200k classes takes 7.6ms (The test is a bit random on when it does the class unloading).
Testing: tier1-5
Thanks,
Thomas
-------------
Commit messages:
- * cleanup
- * improve clean_subklass() to return the last live Klass to avoid the repeating the walk
- Merge branch 'master' into 8363932-klasstaskcleaning-distribution
- * somewhat fixed logging
- * cleanup
- * fix includes
- * some more changes, works now?
- * some attempts to improve class unloading
Changes: https://git.openjdk.org/jdk/pull/27316/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27316&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8363932
Stats: 116 lines in 7 files changed: 6 ins; 61 del; 49 mod
Patch: https://git.openjdk.org/jdk/pull/27316.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/27316/head:pull/27316
PR: https://git.openjdk.org/jdk/pull/27316
More information about the hotspot-runtime-dev
mailing list