1 # Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
2 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 #
4 # This code is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License version 2 only, as
6 # published by the Free Software Foundation.
7 #
8 # This code is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 # version 2 for more details (a copy is included in the LICENSE file that
12 # accompanied this code).
13 #
14 # You should have received a copy of the GNU General Public License version
15 # 2 along with this work; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 #
18 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 # or visit www.oracle.com if you need additional information or have any
20 # questions.
21
22 #===============================================================================
23 # Leyden-premain + spring-petclinic warmup (https://github.com/spring-projects/spring-petclinic)
24 #
25 # Build spring-petclinic:
26 # make app
27 #
28 # Build all leyden optimization artifacts (this is using the older "4 step training run" which will be simplified):
29 # make aot
30 #
31 # Uses JMeter to drive the load to the petclinic application.
32 # Duration of the load and number of threads used by JMeter to drive the load
33 # is controlled by JMETER_DURATION and JMETER_THREADS variables respectively.
34 # JMETER_CPUS and APP_CPUS variables control the cpus to be used for running the jmeter and app respectively.
35 #
36 # Run warmup with baseline
37 # make -f WarmupMakefile warmup-bl
38 #
39 # Run warmup with only preload optimizations
40 # make -f WarmupMakefile warmup-preload
41 #
42 # Run warmup with training data generated for the startup
43 # make -f WarmupMakefile warmup-st
44 #
45 # Run warmup with training data generated by the jmeter load
46 # make -f WarmupMakefile warmup-lt
47 #
48 # Run with startup training data and aot
49 # make -f WarmupMakefile warmup-st-aot
50 #
51 # Run with startup training data and aot
52 # make -f WarmupMakefile warmup-lt-aot
53 #
54 # Run all configurations
55 # make -f WarmupMakefile run
56 #
57 # Use warmup_result.sh to process the generated jmeter log files to create CSV files
58 # that can be used for plotting throughput graphs
59 #
60 # Set the following to point to JDK 17 and your Leyden JDK build.
61 #
62 # *** NOTE: JDK 17 (or 21??) is needed to build spring-petclinic-3.2.0-SNAPSHOT.jar
63 JDK17_HOME = /jdk3/official/jdk17
64 #baseline java
65 BL_HOME = /jdk3/official/jdk-latest
66 PREMAIN_HOME = /jdk3/bld/le4/images/jdk
67 #===============================================================================
68
69 $(error This makefile no longer works. Need to update it to use -XX:AOTCache flags)
70
71 # Usually there's no need to change the following
72 JAR_CMD = ${JDK17_HOME}/bin/jar
73 JDK17_JAVA = ${JDK17_HOME}/bin/java
74 PREMAIN_JAVA = ${PREMAIN_HOME}/bin/java
75 BL_JAVA = ${BL_HOME}/bin/java
76 PC_REPO = petclinic-snapshot-warmup
77 PC_JAVA_SOURCES = ${PC_REPO}/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
78 PC_APP_JAR = ${PC_REPO}/target/spring-petclinic-3.2.0-SNAPSHOT.jar
79 PC_APP_UNPACKED = ${PC_REPO}/target/unpacked
80 JMETER_DIR = apache-jmeter-5.5
81 JMETER_BIN = ${JMETER_DIR}/bin/jmeter
82 JMETER_ZIP = ${JMETER_DIR}.zip
83 JMETER_URL = https://archive.apache.org/dist/jmeter/binaries/${JMETER_ZIP}
84
85 # This is for uploading to artifactory, to be tested with
86 # ../../runtime/cds/appcds/leyden/SpringPetClinic.java
87 PC_APP_UNPACKED_ZIP = ${PC_REPO}/target/spring-petclinic-3.2.0.zip
88
89 PC_MAIN_CLASS = org.springframework.samples.petclinic.PetClinicApplication
90 PC_CLASSLIST = spring-petclinic.classlist
91 PC_STATIC_JSA = spring-petclinic.static.jsa
92 PC_DYNAMIC_ST_JSA = spring-petclinic.dynamic-st.jsa
93 PC_DYNAMIC_LT_JSA = spring-petclinic.dynamic-lt.jsa
94 PC_DYNAMIC_NOTRAINING_JSA = spring-petclinic.dynamic-notraining.jsa
95 PC_ST_CACHED_CODE = spring-petclinic.code-st.jsa
96 PC_LT_CACHED_CODE = spring-petclinic.code-lt.jsa
97
98 PC_BL_CLASSLIST = spring-petclinic.bl_classlist
99 PC_STATIC_BL_JSA = spring-petclinic.static_bl.jsa
100 PC_DYNAMIC_BL_JSA = spring-petclinic.dynamic_bl.jsa
101
102 PC_CDS_PREIMAGE = spring-petclinic.cds.preimage
103 PC_CDS = spring-petclinic.cds
104
105 JMETER_DURATION = 180
106 JMETER_THREADS = 1
107 JMETER_CPUS = 12-13
108 APP_CPUS = 14-19
109
110 # TODO: should we add -Dspring.context.exit=onRefresh to command line??
111 # This will make the JVM quit after printing this line:
112 #
113 # 4:21.639 ... o.s.b.a.e.web.EndpointLinksResolver : Exposing 13 endpoint(s) beneath base path '/actuator'
114 #
115 # Whereas -DautoQuit=true will make it exit after printing the following (a little bit of application code is executed)
116 #
117 # 4:21.665 ... o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path ''
118 # 4:21.666 ... o.s.s.petclinic.PetClinicApplication : Started PetClinicApplication in 1.358 seconds (process running for 1.584)
119 # #### Booted and returned in 1453ms
120 # 4:21.692 ... j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
121 # 4:21.693 ... com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
122 # 4:21.694 ... com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
123 HEAP_SIZE = -Xmx2g
124 UNPACKED_CMDLINE = $(HEAP_SIZE) -cp @${PC_APP_UNPACKED}/classpath -DautoQuit=true -Dspring.aot.enabled=true -Dspring.output.ansi.enabled=NEVER ${PC_MAIN_CLASS}
125
126 all: check git app aot
127
128 check:
129 @if ${JDK17_JAVA} --version | grep -q '17.*LTS'; then \
130 true; \
131 else \
132 echo JDK17_HOME should point to JDK 17; \
133 exit 1; \
134 fi
135 @if ${PREMAIN_JAVA} -XX:+PrintFlagsFinal --version | grep -q CDSManualFinalImage; then \
136 true; \
137 else \
138 echo PREMAIN_HOME should point to your build of https://github.com/openjdk/leyden/tree/premain; \
139 exit 1; \
140 fi
141
142 # A bunch of quick targets so you can type "make list" to create the classlist, etc
143 git: ${PC_JAVA_SOURCES}
144 app: ${PC_APP_JAR}
145 jmeter: ${JMETER_BIN}
146 unpack: ${PC_APP_UNPACKED}
147
148 # The "4 step training run" workflow -- this will soon be replaced with the new workflow in ../javac_new_workflow/
149 list: ${PC_CLASSLIST}
150 static: ${PC_STATIC_JSA}
151 dynamic: ${PC_DYNAMIC_ST_JSA}
152 aot: ${PC_ST_CACHED_CODE}
153
154 # Check out this specific version of spring-petclinic that we have been testing with.
155 # https://github.com/spring-projects/spring-petclinic/commit/80fd11067c4662486e4c635deceba927375b621c
156 # Author: Dave Syer <dsyer@vmware.com>
157 # Date: Wed Jan 10 05:01:00 2024
158 # Upgrade to Boot 3.2.1
159 ${PC_JAVA_SOURCES}:
160 rm -rf ${PC_REPO}
161 git clone https://github.com/spring-projects/spring-petclinic ${PC_REPO}
162 cd ${PC_REPO}; git reset --hard 80fd11067c4662486e4c635deceba927375b621c
163 cd ${PC_REPO}; git apply ../premain-patch-noautoquit.diff
164
165 ${JMETER_BIN}:
166 rm -fr ${JMETER_DIR}
167 wget ${JMETER_URL}
168 unzip -q ${JMETER_ZIP}
169 ls -l $@
170
171 # Need to touch ${PC_APP_JAR} as mvn wants to set it the release date of 3.2.0-SNAPSHOT
172 ${PC_APP_JAR}: ${PC_JAVA_SOURCES}
173 cd ${PC_REPO}; JAVA_HOME=${JDK17_HOME} mvn -Dmaven.test.skip=true package
174 if test -f ${PC_APP_JAR}; then \
175 touch ${PC_APP_JAR}; \
176 fi
177
178 ${PC_APP_UNPACKED}: ${PC_APP_JAR}
179 rm -rf ${PC_APP_UNPACKED}
180 mkdir -p ${PC_APP_UNPACKED}
181 cd ${PC_APP_UNPACKED} && \
182 ${JAR_CMD} xf ../spring-petclinic-3.2.0-SNAPSHOT.jar && \
183 ${JAR_CMD} cf classes.jar META-INF org && \
184 cd BOOT-INF/classes/ && \
185 ${JAR_CMD} cf classes.jar *
186 echo ${PC_APP_UNPACKED}/classes.jar $$(find ${PC_APP_UNPACKED}/BOOT-INF -name \*.jar | sort) \
187 | sed -e 's/ /:/g' > ${PC_APP_UNPACKED}/classpath
188 ${JAR_CMD} cf0 ${PC_APP_UNPACKED_ZIP} ${PC_APP_UNPACKED}
189 $(MAKE) -f WarmupMakefile run17
190
191 #uncomment this to see the generated classes for dynamic proxies
192 #SAVE_GEN_FILES=-Djdk.proxy.ProxyGenerator.saveGeneratedFiles=true
193
194 define wait-for-startup
195 tail -n+0 -f $@.out | sed --quiet '/Booted and returned/ q'
196 endef
197
198 define exit-app
199 cp application.pid app.pid
200 curl -X POST localhost:8080/actuator/shutdown
201 tail -f --pid=`cat app.pid` /dev/null
202 endef
203
204 # petclinic_test_plan.jmx is derived from https://github.com/spring-projects/spring-petclinic/blob/main/src/test/jmeter/petclinic_test_plan.jmx
205 define run-jmeter
206 taskset -c "${JMETER_CPUS}" ${JMETER_BIN} -JDURATION=${JMETER_DURATION} -JTHREADS=${JMETER_THREADS} -Dsummariser.interval=6 -n -t petclinic_test_plan.jmx | tee tput-$@.log
207 endef
208
209 ${PC_BL_CLASSLIST}: ${PC_APP_UNPACKED}
210 ${BL_JAVA} -Xshare:off -XX:DumpLoadedClassList=${PC_BL_CLASSLIST} \
211 -Xlog:class+load=debug:file=$@.log ${SAVE_GEN_FILES} \
212 ${UNPACKED_CMDLINE} &> $@.out &
213 $(wait-for-startup)
214 $(exit-app)
215 wc -lc $@
216
217 ${PC_CLASSLIST}: ${PC_APP_UNPACKED}
218 ${PREMAIN_JAVA} -Xshare:off -XX:DumpLoadedClassList=${PC_CLASSLIST} \
219 -Xlog:class+load=debug:file=$@.log ${SAVE_GEN_FILES} \
220 ${UNPACKED_CMDLINE} &> $@.out &
221 $(wait-for-startup)
222 $(run-jmeter)
223 $(exit-app)
224 wc -lc $@
225
226 ${PC_STATIC_BL_JSA}: ${PC_BL_CLASSLIST}
227 rm -f ${PC_STATIC_BL_JSA}.log
228 ${BL_JAVA} -Xshare:dump -XX:SharedClassListFile=${PC_BL_CLASSLIST} $(HEAP_SIZE) -cp @${PC_APP_UNPACKED}/classpath \
229 -XX:SharedArchiveFile=${PC_STATIC_BL_JSA} -Xlog:cds=debug,cds+class=debug,cds+heap=warning,cds+resolve=debug:file=$@.log
230 ls -l $@
231
232 ${PC_STATIC_JSA}: ${PC_CLASSLIST}
233 rm -f ${PC_STATIC_JSA}.log
234 ${PREMAIN_JAVA} -Xshare:dump -XX:SharedClassListFile=${PC_CLASSLIST} $(HEAP_SIZE) -cp @${PC_APP_UNPACKED}/classpath \
235 -XX:+AOTClassLinking -XX:+ArchiveDynamicProxies -XX:+ArchiveReflectionData \
236 -XX:+ArchiveLoaderLookupCache -Dcds.debug.archived.packages=1 \
237 -XX:SharedArchiveFile=${PC_STATIC_JSA} -Xlog:cds=debug,cds+class=debug,cds+heap=warning,cds+resolve=debug:file=$@.log
238 ls -l $@
239
240 ${PC_DYNAMIC_BL_JSA}: ${PC_STATIC_BL_JSA}
241 rm -f ${PC_DYNAMIC_BL_JSA} ${PC_DYNAMIC_BL_JSA}.log
242 ${BL_JAVA} -XX:SharedArchiveFile=${PC_STATIC_BL_JSA} -XX:ArchiveClassesAtExit=${PC_DYNAMIC_BL_JSA} \
243 -Xlog:cds=debug,cds+class=debug,cds+resolve=debug:file=$@.log \
244 ${UNPACKED_CMDLINE} &> $@.out &
245 $(wait-for-startup)
246 $(exit-app)
247 ls -l $@
248
249 ${PC_DYNAMIC_NOTRAINING_JSA}: ${PC_STATIC_JSA}
250 rm -f ${PC_DYNAMIC_NOTRAINING_JSA} ${PC_DYNAMIC_NOTRAINING_JSA}.log
251 ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_STATIC_JSA} -XX:ArchiveClassesAtExit=${PC_DYNAMIC_NOTRAINING_JSA} \
252 -Xlog:cds=debug,cds+class=debug,cds+resolve=debug:file=$@.log \
253 ${UNPACKED_CMDLINE} &> $@.out &
254 $(wait-for-startup)
255 $(exit-app)
256 ls -l $@
257
258 ${PC_DYNAMIC_ST_JSA}: ${PC_STATIC_JSA}
259 rm -f ${PC_DYNAMIC_ST_JSA} ${PC_DYNAMIC_ST_JSA}.log
260 ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_STATIC_JSA} -XX:ArchiveClassesAtExit=${PC_DYNAMIC_ST_JSA} \
261 -Xlog:cds=debug,cds+class=debug,cds+resolve=debug:file=$@.log \
262 -XX:+UnlockDiagnosticVMOptions -XX:+AOTRecordTraining ${UNPACKED_CMDLINE} &> $@.out &
263 $(wait-for-startup)
264 $(exit-app)
265 ls -l $@
266
267 ${PC_DYNAMIC_LT_JSA}: ${PC_STATIC_JSA}
268 rm -f ${PC_DYNAMIC_LT_JSA} ${PC_DYNAMIC_LT_JSA}.log
269 ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_STATIC_JSA} -XX:ArchiveClassesAtExit=${PC_DYNAMIC_LT_JSA} \
270 -Xlog:cds=debug,cds+class=debug,cds+resolve=debug:file=$@.log \
271 -XX:+UnlockDiagnosticVMOptions -XX:+AOTRecordTraining ${UNPACKED_CMDLINE} &> $@.out &
272 $(wait-for-startup)
273 $(run-jmeter)
274 $(exit-app)
275 ls -l $@
276
277 ${PC_ST_CACHED_CODE}: ${PC_DYNAMIC_ST_JSA}
278 ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_ST_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining -XX:+StoreCachedCode \
279 -XX:CachedCodeFile=${PC_ST_CACHED_CODE} -XX:CachedCodeMaxSize=512M ${UNPACKED_CMDLINE} &> $@.out &
280 $(wait-for-startup)
281 $(exit-app)
282 ls -l $@
283
284 ${PC_LT_CACHED_CODE}: ${PC_DYNAMIC_LT_JSA}
285 ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_LT_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining -XX:+StoreCachedCode \
286 -Xlog:aot+codecache=debug,cds=debug,cds+class=debug,cds+heap=warning,cds+resolve=debug:file=$@.log \
287 -XX:CachedCodeFile=${PC_LT_CACHED_CODE} -XX:CachedCodeMaxSize=512M ${UNPACKED_CMDLINE} &> $@.out &
288 $(wait-for-startup)
289 $(run-jmeter)
290 $(exit-app)
291 ls -l $@
292
293 ${PC_CDS_PREIMAGE}: ${PC_APP_UNPACKED}
294 rm -f ${PC_CDS_PREIMAGE} ${PC_CDS}
295 ${PREMAIN_JAVA} -XX:+AOTClassLinking \
296 -XX:+ArchiveReflectionData \
297 -XX:+ArchiveDynamicProxies -XX:+ArchiveLoaderLookupCache -XX:CachedCodeMaxSize=512M \
298 -XX:+UnlockDiagnosticVMOptions -XX:+CDSManualFinalImage -XX:CacheDataStore=${PC_CDS} \
299 -Xlog:cds=debug,cds+class=debug,cds+heap=warning,cds+resolve=debug:file=$@.log \
300 ${UNPACKED_CMDLINE} &> $@.out &
301 $(wait-for-startup)
302 $(run-jmeter)
303 $(exit-app)
304 ls -l $@
305
306 ${PC_CDS}: ${PC_CDS_PREIMAGE}
307 rm -f ${PC_CDS}
308 ${PREMAIN_JAVA} -XX:+AOTClassLinking -XX:CachedCodeMaxSize=512M \
309 -XX:+UnlockDiagnosticVMOptions -XX:CDSPreimage=${PC_CDS_PREIMAGE} -XX:CacheDataStore=${PC_CDS} \
310 -Xlog:aot+codecache=debug,cds=debug,cds+class=debug,cds+heap=warning,cds+resolve=debug:file=$@.log \
311 -XX:-AssemblyStepInlining \
312 ${UNPACKED_CMDLINE} &> $@.out
313 ls -l $@
314 ls -l $@.code
315
316 warmup-bl: ${PC_DYNAMIC_BL_JSA} ${JMETER_BIN}
317 time taskset -c "${APP_CPUS}" ${BL_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_BL_JSA} \
318 ${UNPACKED_CMDLINE} &> $@.out &
319 $(wait-for-startup)
320 $(run-jmeter)
321 $(exit-app)
322
323 # run with dynamic archive without training data
324 warmup-preload: ${PC_DYNAMIC_NOTRAINING_JSA} ${JMETER_BIN}
325 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_NOTRAINING_JSA} \
326 ${UNPACKED_CMDLINE} &> $@.out &
327 $(wait-for-startup)
328 $(run-jmeter)
329 $(exit-app)
330
331 # run with dynamic archive with startup training data
332 warmup-st: ${PC_DYNAMIC_ST_JSA} ${JMETER_BIN}
333 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_ST_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining \
334 ${UNPACKED_CMDLINE} &> $@.out &
335 $(wait-for-startup)
336 $(run-jmeter)
337 $(exit-app)
338
339 # run with dynamic archive with load training data
340 warmup-lt: ${PC_DYNAMIC_LT_JSA} ${JMETER_BIN}
341 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_LT_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining \
342 ${UNPACKED_CMDLINE} &> $@.out &
343 $(wait-for-startup)
344 $(run-jmeter)
345 $(exit-app)
346
347 # run with startup training data and aot code
348 warmup-st-aot: ${PC_ST_CACHED_CODE} ${JMETER_BIN}
349 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_ST_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining -XX:+LoadCachedCode \
350 -XX:CachedCodeFile=${PC_ST_CACHED_CODE} ${UNPACKED_CMDLINE} &> $@.out &
351 $(wait-for-startup)
352 $(run-jmeter)
353 $(exit-app)
354
355 # run with load training data and aot code
356 warmup-lt-aot: ${PC_LT_CACHED_CODE} ${JMETER_BIN}
357 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:SharedArchiveFile=${PC_DYNAMIC_LT_JSA} -XX:+UnlockDiagnosticVMOptions -XX:+AOTReplayTraining -XX:+LoadCachedCode \
358 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:-TraceDeoptimization \
359 -Xlog:init -XX:CachedCodeFile=${PC_LT_CACHED_CODE} ${UNPACKED_CMDLINE} &> $@.out &
360 $(wait-for-startup)
361 $(run-jmeter)
362 $(exit-app)
363
364 # run with new single-step workflow
365 warmup-lt-aot-new: ${PC_CDS}
366 time taskset -c "${APP_CPUS}" ${PREMAIN_JAVA} -XX:CacheDataStore=${PC_CDS} \
367 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation \
368 -Xlog:init ${UNPACKED_CMDLINE} &> $@.out &
369 $(wait-for-startup)
370 $(run-jmeter)
371 $(exit-app)
372
373 run: warmup-bl warmup-preload warmup-st warmup-lt warmup-st-aot warmup-lt-aot warmup-lt-aot-new
374
375 run17: ${PC_APP_UNPACKED}
376 time ${JDK17_JAVA} ${UNPACKED_CMDLINE} &> $@.out &
377 $(wait-for-startup)
378 $(exit-app)
379
380
381 clean: clean0
382 rm -rf *~ ${PC_REPO}
383
384 # clean the the leyden artifacts
385 clean0:
386 rm -fv spring-petclinic.* *.out tput-*.log app.pid