< prev index next >

README.md

Print this page

  1 # Welcome to the JDK!




























































  2 
  3 For build instructions please see the
  4 [online documentation](https://openjdk.org/groups/build/doc/building.html),
  5 or either of these files:
  6 
  7 - [doc/building.html](doc/building.html) (html version)
  8 - [doc/building.md](doc/building.md) (markdown version)
  9 
 10 See <https://openjdk.org/> for more information about the OpenJDK
 11 Community and the JDK and see <https://bugs.openjdk.org> for JDK issue
 12 tracking.



































































































































































































































































































































































































































































































































































  1 # Welcome to the Leyden Prototype Repository
  2 
  3 The purpose of the Leyden repository is to prototype improvements to
  4 the startup time, time to peak performance, and footprint of Java programs, as a part of
  5 [Project Leyden](https://openjdk.org/projects/leyden). We solicit feedback from
  6 the Java community, with the hope that some of these improvements can eventually be
  7 incorporated into future JDK releases.
  8 
  9 ## 0. Disclaimers
 10 
 11 - *This repository contains experimental and unstable code. It is not intended to be used
 12    in a production environment.*
 13 - *This repository is intended for developers of the JDK, and advanced Java developers who
 14    are familiar with building the JDK.*
 15 - *The experimental features in this repository may be changed or removed without notice.
 16    Command line flags and workflows will change.*
 17 - *The benchmarks results reported on this page are for illustrative purposes only. Your
 18    applications may get better or worse results.*
 19 
 20 To try out the Leyden prototype without building it from source code, please download the
 21 Leyden EA Release from [https://jdk.java.net/leyden/](https://jdk.java.net/leyden/).
 22 
 23 ## 1. Overview
 24 
 25 As of JDK 25, the Leyden Project has successfully delivered ahead-of-time (AOT)
 26 optimizations JEPs:
 27 
 28 - [JEP 483 - Ahead-of-Time Class Loading & Linking](https://openjdk.org/jeps/483)
 29 - [JEP 514 - Ahead-of-Time Command-Line Ergonomics](https://openjdk.org/jeps/514)
 30 - [JEP 515 - Ahead-of-Time Method Profiling](https://openjdk.org/jeps/515)
 31 
 32 Please refer to the above JEPs for a detailed discussion of AOT optimizations.
 33 
 34 The Leyden "[premain](https://github.com/openjdk/leyden/blob/premain/)" prototype
 35 includes new experimental AOT optimizations that are not yet integrated into the JDK mainline:
 36 
 37 - **[Ahead-of-Time Code Compilation (JEP draft 8335368)](https://openjdk.org/jeps/8335368)**: Methods that are frequently used during the training run can be
 38   compiled and stored along with the AOT cache. As a result, as soon as the application starts up
 39   in the production run, its methods can be natively executed.
 40   - This feature is enabled by default when you create an AOT cache. It can be disabled with the diagnostic
 41     flag `-XX:-AOTCodeCaching`.
 42 
 43 - **Ahead-of-time generation of [Dynamic Proxies](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/reflect/Proxy.html)**:
 44   Dynamic proxies are frequently used by popular application frameworks. We can improve start-up time by generating these proxies ahead of time.
 45   - This feature is enabled by default when you create an AOT cache. It can be disabled with the diagnostic
 46     flag `-XX:-ArchiveDynamicProxies`.
 47 
 48 - **Ahead-of-time generation of reflection data**: Reflection data (such as instances of
 49   `java.lang.reflect.Method`) are generated by the JVM to support `java.lang.reflect` operations. We can
 50   generate these ahead of time to improve start-up.
 51   - This feature is enabled by default when you create an AOT cache. It can be disabled with the diagnostic
 52     flag `-XX:-ArchiveReflectionData`.
 53 
 54 - **Class Not Found Cache**: Sometimes application frameworks repeatedly try to load classes that do not exist. This optimization allows such failing lookups to be done quickly without repeatedly scanning the class path.
 55   - This feature is enabled by default when you create an AOT cache. It can be disabled with the diagnostic
 56     flag `-XX:-ArchiveLoaderLookupCache`.
 57 
 58 ## 2. Building the Leyden Repository
 59 
 60 The Leyden Repository can be built in the same way as the main-line JDK repository.
 61 Please use the "premain" branch. I.e., [https://github.com/openjdk/leyden/tree/premain](https://github.com/openjdk/leyden/tree/premain).
 62 
 63 For build instructions please see the
 64 [online documentation](https://openjdk.org/groups/build/doc/building.html),
 65 or either of these files:
 66 
 67 - [doc/building.html](doc/building.html) (html version)
 68 - [doc/building.md](doc/building.md) (markdown version)
 69 
 70 See <https://openjdk.org/> for more information about the OpenJDK
 71 Community and the JDK and see <https://bugs.openjdk.org> for JDK issue
 72 tracking.
 73 
 74 ## 3. Trying out Leyden Features
 75 
 76 The easiest way to try out the Leyden optimizations is to build a JVM from the Leyden repository, and use it with your application with the `-XX:AOTCache` flag.
 77 
 78 
 79 Here's a small benchmark that uses the JDK's built-in
 80 [`JavaCompiler`](https://docs.oracle.com/en/java/javase/21/docs/api/java.compiler/javax/tools/JavaCompiler.html)
 81 class to compile some Java source files. This benchmark spends a significant amount of start-up time
 82 setting up the classes used by `JavaCompiler`, so it will benefit from the Leyden features.
 83 
 84 First, download [JavacBenchApp.java](test/setup_aot/JavacBenchApp.java) and compile it into a JAR file.
 85 
 86 (Remember to use the `java` program that you built from the Leyden repository.)
 87 
 88 ```
 89 $ javac JavacBenchApp.java
 90 $ jar cvf JavacBenchApp.jar JavacBenchApp*.class
 91 added manifest
 92 adding: JavacBenchApp$ClassFile.class(in = 1608) (out= 787)(deflated 51%)
 93 adding: JavacBenchApp$FileManager.class(in = 2090) (out= 979)(deflated 53%)
 94 adding: JavacBenchApp$SourceFile.class(in = 1351) (out= 671)(deflated 50%)
 95 adding: JavacBenchApp.class(in = 7571) (out= 3302)(deflated 56%)
 96 ```
 97 
 98 We can run this benchmark without any AOT optimizations. It takes 893 ms:
 99 
100 ```
101 $ java -cp JavacBenchApp.jar JavacBenchApp 50
102 Generated source code for 51 classes and compiled them in 893 ms
103 ```
104 
105 To use AOT optimizations for JavacBenchApp, we should first perform a _training run_ and
106 capture the profiling information into `JavacBenchApp.aotconfig`
107 
108 ```
109 $ java -XX:AOTMode=record -XX:AOTConfiguration=JavacBenchApp.aotconfig \
110        -cp JavacBenchApp.jar JavacBenchApp 50
111 $ ls -l JavacBenchApp.aotconfig
112 -rw-rw-r-- 1 iklam iklam 27652096 Mar  3 16:23 JavacBenchApp.aotconfig
113 ```
114 
115 With the `JavacBenchApp.aotconfig` file, we can create the AOT cache. This is called the _assembly phase_:
116 
117 ```
118 $ java -XX:AOTMode=create -XX:AOTConfiguration=JavacBenchApp.aotconfig \
119        -cp JavacBenchApp.jar -XX:AOTCache=JavacBenchApp.aot
120 $ ls -l JavacBenchApp.aot
121 -r--r--r-- 1 iklam iklam 42332160 Mar  3 16:58 JavacBenchApp.aot
122 ```
123 
124 Alternatively, you can also combine the training run and assembly phase with a single command:
125 
126 ```
127 $ java -XX:AOTCacheOutput=JavacBenchApp.aot \
128        -cp JavacBenchApp.jar JavacBenchApp 50
129 $ ls -l JavacBenchApp.aot
130 -r--r--r-- 1 iklam iklam 42332160 Mar  3 16:58 JavacBenchApp.aot
131 ```
132 
133 Now, we can make a _production run_ of the program using the AOT cache `JavacBenchApp.aot`. It finishes in 423 ms, or more than twice as fast as
134 before.
135 
136 ```
137 $ java -XX:AOTCache=JavacBenchApp.aot -cp JavacBenchApp.jar JavacBenchApp 50
138 Generated source code for 51 classes and compiled them in 423 ms
139 ```
140 
141 ### Ending the Training Run Early
142 
143 By default, training runs end when the application terminates.  You have two other options to end training runs:
144 
145 - `-XX:AOTEndTrainingOnMethodEntry=<method1,method2,...>[,count=100]`
146 - `jcmd <pid> AOT.end_training`
147 
148 Note that `-XX:AOTEndTrainingOnMethodEntry` uses the same format as `-XX:CompileOnly` and the default count is 1.
149 
150 See [EndTrainingOnMethodEntry.java](test/hotspot/jtreg/runtime/cds/appcds/leyden/EndTrainingOnMethodEntry.java) for a test case.
151 
152 ### Diagnosing Potential Performance Issues
153 
154 As mentioned below, parts or all of the AOT cache may be disabled under certain circumstances. This may lead
155 to lower performance than expected. To diagnose potential performance issues, you can add `-Xlog:aot*` to the
156 command line to see detailed information about what parts of the AOT cache are being utilized. For example, if the
157 the AOT-compiled code cannot be loaded, you will see a log message like this:
158 
159 ```
160 [0.008s][info][aot,codecache,init] Mapped 652184 bytes at address 0x00007f491005f028 from AOT Code Cache
161 [0.008s][info][aot,codecache,init] Loaded 439 AOT code entries from AOT Code Cache
162 [0.008s][info][aot,codecache,init] Unable to use AOT Code Cache.
163 ```
164 
165 ### Diagnostic VM Flags
166 
167 By default, all of the optimizations described
168 in the [Overview](#1-overview) section above are enabled by default. This ensures that you can get all the optimizations
169 without specifying them individually.
170 
171 For diagnostic purposes, you can selectively disable some of the options:
172 
173 - The `-XX:+AOTCodeCaching` flag affects only the assembly phase and the production run.
174 - The `-XX:+AOTRecordTraining` flag affects only the training run and the assembly phase.
175 - The `-XX:+AOTReplayTraining` flag affects only the production run.
176 - All other options affect only the assembly phase.
177 
178 For example, you can disable the loading of AOT-compiled methods during the production run. Notice that the benchmark now
179 starts more slowly than it did when AOT-compiled methods was loaded.
180 
181 ```
182 $ java -XX:AOTCache=JavacBenchApp.aot -Xlog:cds=error -XX:-AOTCodeCaching \
183        -cp JavacBenchApp.jar JavacBenchApp 50
184 Generated source code for 51 classes and compiled them in 647 ms
185 ```
186 
187 You can also disable AOT compilation in the assembly phase. Note that the size of the AOT
188 cache is smaller because it no longer has AOT-compiled methods.
189 
190 ```
191 $ java -XX:AOTMode=create -XX:AOTConfiguration=JavacBenchApp.aotconfig \
192        -cp JavacBenchApp.jar \
193        -XX:AOTCache=JavacBenchApp.aot -XX:-AOTCodeCaching
194 $ ls -l JavacBenchApp.aot
195 -r--r--r-- 1 iklam iklam 29990912 Mar  3 16:34 JavacBenchApp.aot
196 ```
197 
198 
199 ## 4. Limitations of the Leyden Prototype
200 
201 When trying out the Leyden prototype, please pay attention to the following limitations.
202 
203 ### The Same CPU Must be Used between Training and Production Runs
204 
205 The AOT-compiled code will be only used if the production run is on a machine with the same type of CPU
206 as used in the training run and assembly phase. If this is not the case (for example, the production run is on
207 a machine that has different AVX capabilities), the AOT-compiled code will be ignored.
208 
209 
210 ### The Same Garbage Collector Must be Used between Training and Production Runs
211 
212 The AOT cache generated by the Leyden prototype includes machine instructions that are specific to
213 the garbage collector. We recommend that you explicitly specify the same collector during both
214 training and production runs. For example, if you prefer to use the SerialGC:
215 
216 ```
217 # assembly phase.
218 $ java -XX:AOTMode=create -XX:AOTConfiguration=JavacBenchApp.aotconfig \
219        -cp JavacBenchApp.jar \
220        -XX:AOTCache=JavacBenchApp.aot -XX:+UseSerialGC
221 
222 # production run
223 $ java -XX:AOTCache=JavacBenchApp.aot -XX:+UseSerialGC -cp JavacBenchApp.jar \
224        JavacBenchApp 50
225 ```
226 
227 Otherwise, the AOT cache may not be usable for the production run, leading to suboptimal performance.
228 For example, sometimes you may perform the assembly phase run on a large development host, and then use
229 a container to run the application in a small production node. In the following scenario, as the collector
230 is not explicitly specified, the VM will automatically pick G1 for the assembly phase, and SerialGC for the
231 production run (due to its limited amount of memory):
232 
233 ```
234 # Assembly phase (uses G1 by default)
235 $ java -XX:AOTMode=create -XX:AOTConfiguration=JavacBenchApp.aotconfig \
236        -cp JavacBenchApp.jar -XX:AOTCache=JavacBenchApp.aot
237 
238 # Production run (uses SerialGC)
239 $ docker run --rm -v /repos/leyden/build/linux-x64/images/jdk:/jdk -v $(pwd):/test \
240     --memory=1024m \
241     container-registry.oracle.com/java/openjdk \
242     bash -c 'cd /test; ' \
243             '/jdk/bin/java -XX:AOTCache=JavacBenchApp.aot ' \
244             '    -cp JavacBenchApp.jar JavacBenchApp 50'
245 [0.001s][error][aot] AOT cache has aot-linked classes. It cannot be used because
246                      GC used during dump time (G1) is not the same as runtime (Serial)
247 [0.001s][error][aot] An error has occurred while processing the AOT cache.
248 [0.001s][error][aot] Unable to map shared spaces
249 Error occurred during initialization of VM
250 Unable to use AOT cache.
251 ```
252 
253 ### Only G1GC, SerialGC, ParallelGC, EpsilonGC, ShenandoahGC are Supported
254 
255 Currently, if you use any other garbage collector in combination with `-XX:AOTMode` or `-XX:AOTCache`, the VM will
256 exit with an error.
257 
258 ```
259 $ java -XX:AOTMode=record -XX:AOTConfiguration=JavacBenchApp.aotconfig \
260        -cp JavacBenchApp.jar -XX:+UseZGC JavacBenchApp 50
261 Error occurred during initialization of VM
262 Cannot create the AOT configuration file: UseCompressedClassPointers must be enabled,
263 and collector must be G1, Parallel, Serial, Epsilon, or Shenandoah
264 ```
265 
266 ## 5. Benchmarking
267 
268 We use a small set of benchmarks to demonstrate the performance of the optimizations in the Leyden repo.
269 
270 | Benchmark  | Source |
271 | ------------- | ------------- |
272 |[helidon-quickstart-se](test/hotspot/jtreg/premain/helidon-quickstart-se) | https://helidon.io/docs/v4/se/guides/quickstart|
273 |[javac-bench](test/hotspot/jtreg/premain/javac_bench) | Using Javac to compile 50 source files |
274 |[micronaut-first-app](test/hotspot/jtreg/premain/micronaut-first-app) | https://guides.micronaut.io/latest/creating-your-first-micronaut-app-maven-java.html|
275 |[quarkus-getting-started](test/hotspot/jtreg/premain/quarkus-getting-started) | https://quarkus.io/guides/getting-started|
276 |[spring-boot-getting-started](test/hotspot/jtreg/premain/spring-boot-getting-started) | https://spring.io/guides/gs/spring-boot|
277 |[spring-petclinic](test/hotspot/jtreg/premain/spring-petclinic) | https://github.com/spring-projects/spring-petclinic|
278 
279 ### Benchmarking Against JDK Main-line
280 
281 To can compare the performance of Leyden vs the main-line JDK, you need:
282 
283 - An official build of JDK 21
284 - An up-to-date build of the JDK main-line
285 - The latest Leyden build
286 - Maven (ideally 3.8 or later, as required by some of the demos). Note: if you are behind
287   a firewall, you may need to [set up proxies for Maven](https://maven.apache.org/guides/mini/guide-proxies.html)
288 
289 The same steps are used for benchmarking all of the above demos. For example:
290 
291 ```
292 $ cd test/hotspot/jtreg/premain/helidon-quickstart-se
293 $ make PREMAIN_HOME=/repos/leyden/build/linux-x64/images/jdk \
294        MAINLINE_HOME=/repos/jdk/build/linux-x64/images/jdk \
295        BLDJDK_HOME=/usr/local/jdk21 \
296        bench
297 run,mainline default,mainline custom static cds,mainline aot cache,premain aot cache
298 1,456,229,156,117
299 2,453,227,157,117
300 3,455,232,155,116
301 4,448,230,154,114
302 5,440,228,156,114
303 6,446,228,156,114
304 7,448,232,156,114
305 8,465,261,159,114
306 9,448,226,157,113
307 10,442,233,154,114
308 Geomean,450.05,232.41,155.99,114.69
309 Stdev,6.98,9.72,1.41,1.35
310 Markdown snippets in mainline_vs_premain.md
311 ```
312 
313 The above command runs each configuration 10 times, in an interleaving order. This way
314 the noise of the system (background processes, thermo throttling, etc) is more likely to
315 be spread across the different runs.
316 
317 As is typical for benchmarking start-up performance, the numbers are not very steady.
318 It is best to plot
319 the results (as saved in the file `mainline_vs_premain.csv`) in a spreadsheet to check for
320 noise and other artifacts.
321 
322 The "make bench" target also generates GitHub markdown snippets (in the file `mainline_vs_premain.md`) for creating the
323 graphs below.
324 
325 ### Benchmarking Between Two Leyden Builds
326 
327 This is useful for Leyden developers to measure the benefits of a particular optimization.
328 The steps are similar to above, but we use the "make compare_premain_builds" target:
329 
330 ```
331 $ cd helidon-quickstart-se
332 $ make PM_OLD=/repos/leyden_old/build/linux-x64/images/jdk \
333        PM_NEW=/repos/leyden_new/build/linux-x64/images/jdk \
334        BLDJDK_HOME=/usr/local/jdk21 \
335        compare_premain_builds
336 Old build = /repos/leyden_old/build/linux-x64/images/jdk with options
337 New build = /repos/leyden_new/build/linux-x64/images/jdk with options
338 Run,Old CDS + AOT,New CDS + AOT
339 1,110,109
340 2,131,111
341 3,118,115
342 4,110,108
343 5,117,110
344 6,114,109
345 7,110,109
346 8,118,110
347 9,110,110
348 10,113,114
349 Geomean,114.94,110.48
350 Stdev,6.19,2.16
351 Markdown snippets in compare_premain_builds.md
352 ```
353 
354 Please see [test/hotspot/jtreg/premain/lib/Bench.gmk](test/hotspot/jtreg/premain/lib/Bench.gmk) for more details.
355 
356 Note: due to the variability of start-up time, the benefit of minor improvements may
357 be difficult to measure.
358 
359 ### Preliminary Benchmark Results
360 
361 The following charts show the relative start-up performance of the Leyden/Premain branch vs
362 the JDK main-line.
363 
364 For example, a number of "premain aot cache: 255" indicates that if the application takes
365 1000 ms to start-up with the JDK main-line, it takes only 255 ms to start up when all the
366 current set of Leyden optimizations are enabled.
367 
368 The benchmark results are collected with `make bench` in the following directories under [test/hotspot/jtreg/premain](test/hotspot/jtreg/premain):
369 
370 - `helidon-quickstart-se`
371 - `javac-bench`
372 - `micronaut-first-app`
373 - `quarkus-getting-started`
374 - `spring-boot-getting-started`
375 - `spring-petclinic`
376 
377 The meaning of the four rows in the following charts:
378 
379 | Row  | Meaning |
380 | ------------- | ------------- |
381 | **mainline default**            |Run benchmark with no optimizations|
382 | **mainline custom static cds**  |Run benchmark with a custom static CDS archive|
383 | **mainline aot cache**          |Run benchmark with a custom AOT cache (JDK mainline)|
384 | **premain aot cache**           |Run benchmark with a custom AOT cache (Leyden Premain Prototype)|
385 
386 We have benchmark results from two types of configurations using the
387 script [test/hotspot/jtreg/premain/bench_data/do_bench.sh](test/hotspot/jtreg/premain/bench_data/do_bench.sh):
388 
389 - Desktop/Server Class: these are the results when running on a modern desktop or server, using the
390   command `bash bench_data/do_bench.sh`.
391 - 2 Cores Only: these are the results when running in a limited configuration where only two cores.
392   are available, using the command `taskset -c 1,2 bash bench_data/do_bench.sh`
393 
394 The 2 Cores Only setting is intended to emulate microservice configurations where a very small number
395 of cores are allocated for small Java programs. In this setting, the JIT compiler may compete for CPU
396 with the Java program, making start-up slower. The **premain aot cache** numbers usually are much better in
397 this setting because most of the start-up code has been AOT-compiled, so the app can spend most of the
398 available CPUs to execute application logic.
399 
400 These JDK versions were used in the comparisons:
401 
402 - JDK main-line: JDK 25, build 25+37-LTS-3491
403 - Leyden: https://github.com/openjdk/leyden/tree/ce150637130086ad2b47916d66148007f5331a28
404 
405 For details information about the hardware and raw numbers, see [bench.20250930.txt](test/hotspot/jtreg/premain/bench_data/bench.20250930.txt)
406  and [bench.20250930-2cpu.txt](test/hotspot/jtreg/premain/bench_data/bench.20250930-2cpu.txt)
407 
408 #### Premain AOT Cache Summary
409 
410 This is the speed up of **premain aot cache** vs **mainline default** in the two types of configurations
411 
412 | Benchmark | Desktop/Server Class (28 Cores) | 2 Cores Only|
413 |:-------------|-------------:| -------------:|
414 | Helidon Quick Start | 3.59x | 4.11x |
415 | JavacBenchApp 50 source files | 2.21x | 3.17x |
416 | Micronaut First App Demo | 2.91x | 4.90x |
417 | Quarkus Getting Started Demo | 2.97x | 3.74x |
418 | Spring-boot Getting Started Demo | 4.13x | 4.70x |
419 | Spring PetClinic Demo | 3.33x | 3.03x |
420 
421 ### 5.1 Benchmark Results - Desktop/Server Class (28 Cores)
422 
423 #### Helidon Quick Start (3.59x improvement - Desktop/Server Class (28 Cores))
424 
425 ```mermaid
426 ---
427 config:
428     theme: "forest"
429     xyChart:
430         chartOrientation: horizontal
431         height: 300
432 ---
433 xychart-beta
434     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
435     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
436     bar [1000, 520, 350, 279]
437 ```
438 
439 #### JavacBenchApp 50 source files (2.21x improvement - Desktop/Server Class (28 Cores))
440 
441 ```mermaid
442 ---
443 config:
444     theme: "forest"
445     xyChart:
446         chartOrientation: horizontal
447         height: 300
448 ---
449 xychart-beta
450     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
451     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
452     bar [1000, 785, 572, 452]
453 ```
454 
455 #### Micronaut First App Demo (2.91x improvement - Desktop/Server Class (28 Cores))
456 
457 ```mermaid
458 ---
459 config:
460     theme: "forest"
461     xyChart:
462         chartOrientation: horizontal
463         height: 300
464 ---
465 xychart-beta
466     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
467     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
468     bar [1000, 482, 387, 344]
469 ```
470 
471 #### Quarkus Getting Started Demo (2.97x improvement - Desktop/Server Class (28 Cores))
472 
473 ```mermaid
474 ---
475 config:
476     theme: "forest"
477     xyChart:
478         chartOrientation: horizontal
479         height: 300
480 ---
481 xychart-beta
482     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
483     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
484     bar [1000, 499, 417, 337]
485 ```
486 
487 #### Spring-boot Getting Started Demo (4.13x improvement - Desktop/Server Class (28 Cores))
488 
489 ```mermaid
490 ---
491 config:
492     theme: "forest"
493     xyChart:
494         chartOrientation: horizontal
495         height: 300
496 ---
497 xychart-beta
498     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
499     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
500     bar [1000, 492, 332, 242]
501 ```
502 
503 #### Spring PetClinic Demo (3.33x improvement - Desktop/Server Class (28 Cores))
504 
505 ```mermaid
506 ---
507 config:
508     theme: "forest"
509     xyChart:
510         chartOrientation: horizontal
511         height: 300
512 ---
513 xychart-beta
514     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
515     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
516     bar [1000, 619, 568, 301]
517 ```
518 ### 5.2 Benchmark Results - 2 Cores Only
519 
520 #### Helidon Quick Start (4.11x improvement - 2 Cores Only)
521 
522 ```mermaid
523 ---
524 config:
525     theme: "forest"
526     xyChart:
527         chartOrientation: horizontal
528         height: 300
529 ---
530 xychart-beta
531     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
532     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
533     bar [1000, 585, 459, 244]
534 ```
535 
536 #### JavacBenchApp 50 source files (3.17x improvement - 2 Cores Only)
537 
538 ```mermaid
539 ---
540 config:
541     theme: "forest"
542     xyChart:
543         chartOrientation: horizontal
544         height: 300
545 ---
546 xychart-beta
547     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
548     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
549     bar [1000, 845, 674, 315]
550 ```
551 
552 #### Micronaut First App Demo (4.90x improvement - 2 Cores Only)
553 
554 ```mermaid
555 ---
556 config:
557     theme: "forest"
558     xyChart:
559         chartOrientation: horizontal
560         height: 300
561 ---
562 xychart-beta
563     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
564     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
565     bar [1000, 439, 355, 204]
566 ```
567 
568 #### Quarkus Getting Started Demo (3.74x improvement - 2 Cores Only)
569 
570 ```mermaid
571 ---
572 config:
573     theme: "forest"
574     xyChart:
575         chartOrientation: horizontal
576         height: 300
577 ---
578 xychart-beta
579     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
580     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
581     bar [1000, 512, 495, 268]
582 ```
583 
584 #### Spring-boot Getting Started Demo (4.70x improvement - 2 Cores Only)
585 
586 ```mermaid
587 ---
588 config:
589     theme: "forest"
590     xyChart:
591         chartOrientation: horizontal
592         height: 300
593 ---
594 xychart-beta
595     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
596     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
597     bar [1000, 607, 518, 213]
598 ```
599 
600 #### Spring PetClinic Demo (3.03x improvement - 2 Cores Only)
601 
602 ```mermaid
603 ---
604 config:
605     theme: "forest"
606     xyChart:
607         chartOrientation: horizontal
608         height: 300
609 ---
610 xychart-beta
611     x-axis "variant" ["mainline default", "mainline custom static cds", "mainline aot cache", "premain aot cache"]
612     y-axis "Elapsed time (normalized, smaller is better)" 0 --> 1000
613     bar [1000, 632, 572, 330]
614 ```
615 
616 ## 6. More Documentation
617 
618 Please see [test/hotspot/jtreg/premain/](test/hotspot/jtreg/premain) for more information.
< prev index next >