Performance regression in BuiltinClassLoader?
eirbjo at gmail.com
Mon Jan 18 18:34:16 UTC 2021
I've been looking into ZipFile again with the aim to speed up typical
enterprise classloading / resource lookups.
To test the performance impact of my changes, I made a benchmark which
creates an EnterpriseClassLoader (subclass of URLClassLoader) with the jar
files in Spring Petclinic (89 jars with ~30k entries total).
(This is intentionally implemented using a plain main method with no JMH or
warmup since I want to measure a representative cold application startup)
The benchmark measures the time needed to call getResource 30K times, once
for each entry name.
Using 15.0.1, this completes in ~1700 ms
Using 17 master, it completes in 12851 ms
If I run the benchmark from the classpath instead of as a module, the
result is even worse:
15: 1724 ms
17: 21885 ms
If also measure GC collections and times, and get the following:
Collection time: 12 ms
Collection time: 44 ms
(However, a JHM with -prof gc indicates that both 17 and 15 allocate
~5.6Kb/getResource after warmup, so not convinced this needs to be
The EnterpriseClassLoader is a bit clever in that it can perform lookups
using different strategies: Regular parent-first, self-only, or use the
bootstrap / platform system classloaders directly.
Here are the results on 17 using each strategy (benchmark on class path):
PARENT_DELEGATION: 23111 ms
SELF_ONLY: 428 ms
BOOTSTRAP: 8131 ms
PLATFORM: 15149 ms
SYSTEM: 20628 ms
Here are the same results on 15:
PARENT_DELEGATION: 1691 ms
SELF_ONLY: 393 ms
BOOTSTRAP: 579 ms
PLATFORM: 908 ms
SYSTEM: 1368 ms
Note that the delegation chain is Enterprise -> System -> Platform ->
Interesting to note that URLClassLoader itself does not seem to regress
much when only looking up its own resources, while delegating up the chain
Has there been any significant work in class loading / resource lookup
since 15.0.1 that could help explain this regression?
More information about the core-libs-dev