[crac] RFR: 8364156: [CRaC] Recompile methods decompiled during or shortly after C/R [v3]

Timofei Pushkin tpushkin at openjdk.org
Tue Jul 29 09:08:00 UTC 2025


> Implements recording and triggering recompilation of methods decompiled during and shortly after C/R. The length of the "shortly-after" period can be controlled by the user via `-Djdk.crac.recompilation-delay-ms=<long>`, the default is 10ms.
> 
> Measuring the after-restore regression before and after this change shows improvement on hello-world apps. The numbers are the regression of the first after-restore 1 sec iteration vs average over 5 last before-checkpoint 1 sec iterations, i.e. lower means better; mean ± std dev over 30 runs. Measured in a Linux VM on MacOS, with CRIU, with 5ms after-restore recompilation delay.
> 
> |                          | Before      | After       |
> |--------------------------|-------------|-------------|
> | Helidon hello-world      | 0.9 ± 1.2 % | 0.4 ± 1.0 % |
> | Spring boot CRaC example | 9.5 ± 2.4 % | 6.4 ± 2.5 % |
> 
> Currently decompilations are recorded during C/R + during the after-restore delay and then they all get recompiled together. An enhancement planned in the future is to record only during C/R recompiling immediately after restore and during the after-restore delay recompile immediately without recording. This way the recompilations would finish faster, also setting `jdk.crac.recompilation-delay-ms` to a higher value would have less negative impact.
> 
> Implementation notes:
> - Native code (`nmethod`) is considered "decompiled" when `make_not_entrant(...)` is called on it — a new mandatory parameter is added to the signature of this method that controls whether CRaC should consider this particular decompilation for recompilation or not.
>   - The parameter is needed because we do not want to recompile, for example, when `nmethod` is thrown away once a replacement for it has been compiled (e.g. on another compilation level).
>   - The parameter has no default so that we get compilation errors when new calls to `make_not_entrant(...)` are introduced in the mainline — we will be deciding whether these new calls should be considered for recompilation or not. If CRaC was in the mainline I would enable the recompilation by default.
> - The new native `CRaCRecorder` class is the core of the implementation — it records the decompilations and handles their recompilation.
>   - `jdk.crac.internal.mirror.Core` notifies it when to start and stop the recording, it also handles the after-restore recompilation delay.
>   - `nmethod.make_not_entrant(...)` notifies it about decompiled code.

Timofei Pushkin 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 16 additional commits since the last revision:

 - Resolve issues brought-in by the merge
 - Merge remote-tracking branch 'openjdk-crac/crac' into recompile
 - Implement flag-related review suggestions
 - Cleanup tests
 - Remove erroneously added assert
 - Bring back erroneously removed locking
 - Fix RedefineClasses defence
 - Reduce default recompilation delay
 - Fix NaturalDecompilationTest on Windows
 - Make decompilation more reliable in NaturalDecompilationTest
 - ... and 6 more: https://git.openjdk.org/crac/compare/d54797c5...db100b7f

-------------

Changes:
  - all: https://git.openjdk.org/crac/pull/251/files
  - new: https://git.openjdk.org/crac/pull/251/files/536ce035..db100b7f

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=crac&pr=251&range=02
 - incr: https://webrevs.openjdk.org/?repo=crac&pr=251&range=01-02

  Stats: 167522 lines in 2908 files changed: 99603 ins; 46016 del; 21903 mod
  Patch: https://git.openjdk.org/crac/pull/251.diff
  Fetch: git fetch https://git.openjdk.org/crac.git pull/251/head:pull/251

PR: https://git.openjdk.org/crac/pull/251


More information about the crac-dev mailing list