DO NOT MERGE: #34154: test(java25): what an AOT cache actually costs dotCMS - #37425
DO NOT MERGE: #34154: test(java25): what an AOT cache actually costs dotCMS#37425fabrizzio-dotCMS wants to merge 1 commit into
Conversation
AOT adoption in core is zero and the talk had no evidence for it. This adds a self-relaunching demo that drives the record/create/use workflow in child JVMs and reproduces the two constraints that decide whether it is usable here. Findings, all reproduced by the demo rather than asserted: - The cache is bound to the UseCompactObjectHeaders setting it was built with. dotCMS enables that flag in the shipped container and in the test JVMs. On a mismatch the JVM logs the error and KEEPS RUNNING without the cache, exit 0 -- startup silently returns to full cost. - A directory on the class path ends the training run outright: "Cannot have non-empty directory in paths", non-zero exit. A JAR records normally. dotCMS serves an exploded WAR with its classes in WEB-INF/classes, so this blocks any measurement rather than degrading it. Verified on JDK 25.0.2. Needs no Maven, no dotCMS classpath and no network; test-compile -pl :dotcms-core --am passes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @fabrizzio-dotCMS's task in 1m 6s —— View job Code Review —
|
Why this exists
Session 2 of the Lunch & Learn (#34154) budgets 3 minutes of concept and 2.5 of dotCMS
application to ahead-of-time computation. It is the only one of the six features in that
half where our adoption is zero and we had no evidence of our own — every other beat is
backed by real code.
This closes that gap by measuring instead of speculating. It is study material for the talk,
not a proposal: DO NOT MERGE.
What it does
AotCacheDemore-launches itself in child JVMs, because-XX:AOTModeand-XX:AOTCacheareread once at startup and no single-JVM test can compare them — the same reason
CompactObjectHeadersDemospawns children. Every phase runs with-XX:+UseCompactObjectHeaders, because that is how dotCMS actually runs.No Maven, no dotCMS classpath, no network. JDK 24+ for
AOTMode; verified on 25.0.2.What it found
1 — The cache is bound to a flag we already set for an unrelated reason.
We enable
UseCompactObjectHeadersincontainer/tomcat9/bin/setenv.shand in the test JVMsin
parent/pom.xml. Any cache we build has to be built with it. On a mismatch the JVM doesnot fail — it reports it and starts anyway, without the cache. Flip that flag in either
direction, in any environment, and the server keeps booting while quietly paying full startup
cost. The only signal is a log line nobody is watching for.
2 — An exploded WAR ends the training run.
Our own classes live in
WEB-INF/classes. This is a blocker to clear before any measurement,not a limitation to design around. (Recording against the current directory,
-cp ., behavesdifferently again: the class is merely skipped as an
Unsupported locationand the dumpsucceeds. Worth knowing before someone reports the two as the same thing.)
3 — The workflow itself is three commands and it works. On the demo's own toy workload the
cached start is roughly 45% faster. Treat that as an order of magnitude and nothing more — it
loads a few hundred classes where dotCMS loads tens of thousands.
The cheapest real first step is not this
dotcms.startup.msis already published —ServletContainerHealthCheckat lines 141, 152and 472. Before any AOT work, plotting the distribution of a number we already collect gives
the baseline that AOT would have to beat. That costs nothing and needs no new code.
Not in scope
dotcms.startup.msdashboard — that needs data from real environments, not a laptop.System.getProperty("dotcms.startup.ms")reads inServletContainerHealthCheckviolatethe Config-only Critical Rule in CLAUDE.md. Noticed, deliberately not fixed here.
Refs #34154