Skip to content

Commit 1bc8a67

Browse files
committed
Add command and weekly job to generate pgo profile
1 parent e3594eb commit 1bc8a67

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

ci.jsonnet

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@
230230
"python-svm-build": gpgate + platform_spec(no_jobs) + platform_spec({
231231
"linux:amd64:jdk-latest" : tier2 + provide(GPY_NATIVE_STANDALONE),
232232
}),
233+
"python-pgo-profile": gpgate_ee + platform_spec(no_jobs) + platform_spec({
234+
"linux:amd64:jdk-latest" : weekly + t("01:30:00") + task_spec({
235+
run: [["mx", "python-native-pgo"]],
236+
logs+: ["default.iprof"],
237+
}),
238+
}),
233239
"python-svm-unittest": gpgate + platform_spec(no_jobs) + platform_spec({
234240
"linux:amd64:jdk-latest" : tier2 + require(GPY_NATIVE_STANDALONE),
235241
"linux:aarch64:jdk-latest" : tier3 + provide(GPY_NATIVE_STANDALONE),

mx.graalpython/mx_graalpython.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,50 @@ def libpythonvm_build_args():
277277
return build_args
278278

279279

280+
def graalpy_native_pgo_build_and_test(args):
281+
"""
282+
Builds a PGO-instrumented GraalPy native standalone, runs the unittests to generate a profile,
283+
then builds a PGO-optimized GraalPy native standalone with the collected profile.
284+
The profile file will be named 'default.iprof' in native image build directory.
285+
"""
286+
import tempfile
287+
288+
with set_env(GRAALPY_PGO_PROFILE=""):
289+
mx.log(mx.colorize("[PGO] Building PGO-instrumented native image", color="yellow"))
290+
native_bin = graalpy_standalone('native', enterprise=True, build=True)
291+
292+
mx.log(mx.colorize("[PGO] Instrumented build complete.", color="yellow"))
293+
294+
mx.log(mx.colorize(f"[PGO] Running graalpytest with instrumented binary: {native_bin}", color="yellow"))
295+
with tempfile.TemporaryDirectory() as d:
296+
with set_env(
297+
GRAALPYTEST_ALLOW_NO_JAVA_ASSERTIONS="true",
298+
GRAAL_PYTHON_VM_ARGS=f"--vm.XX:ProfilesDumpFile={os.path.join(d, '$UUID$.iprof')}"
299+
):
300+
graalpytest(["--python", native_bin, "."])
301+
iprof_path = os.path.join(SUITE.dir, 'default.iprof')
302+
303+
mx.run([
304+
os.path.join(
305+
graalvm_jdk(enterprise=True),
306+
"bin",
307+
f"native-image-configure{'.exe' if mx.is_windows() else ''}",
308+
),
309+
"merge-pgo-profiles",
310+
f"--input-dir={d}",
311+
f"--output-file={iprof_path}"
312+
])
313+
314+
if not os.path.isfile(iprof_path):
315+
mx.abort(f"[PGO] Could not find profile file at expected location: {iprof_path}")
316+
317+
with set_env(GRAALPY_PGO_PROFILE=iprof_path):
318+
mx.log(mx.colorize("[PGO] Building optimized native image with collected profile", color="yellow"))
319+
native_bin = graalpy_standalone('native', enterprise=True, build=True)
320+
321+
mx.log(mx.colorize(f"[PGO] Optimized PGO build complete: {native_bin}", color="yellow"))
322+
323+
280324
def full_python(args, env=None):
281325
"""Run python from standalone build (unless kwargs are given). Does not build GraalPython sources automatically."""
282326

@@ -667,6 +711,16 @@ def graalpy_standalone_home(standalone_type, enterprise=False, dev=False, build=
667711
if BUILD_NATIVE_IMAGE_WITH_ASSERTIONS:
668712
mx_args.append("--extra-image-builder-argument=-ea")
669713

714+
pgo_profile = os.environ.get("GRAALPY_PGO_PROFILE")
715+
if pgo_profile is not None:
716+
if not enterprise or standalone_type != "native":
717+
mx.abort("PGO is only supported on enterprise NI")
718+
if pgo_profile:
719+
mx_args.append(f"--extra-image-builder-argument=--pgo={pgo_profile}")
720+
mx_args.append(f"--extra-image-builder-argument=-H:+PGOPrintProfileQuality")
721+
else:
722+
mx_args.append(f"--extra-image-builder-argument=--pgo-instrument")
723+
670724
if mx_gate.get_jacoco_agent_args() or (build and not DISABLE_REBUILD):
671725
mx_build_args = mx_args
672726
if BYTECODE_DSL_INTERPRETER:
@@ -913,7 +967,9 @@ def graalpytest(args):
913967
python_binary = graalpy_standalone_native()
914968
elif 'graalpy' in os.path.basename(python_binary) or 'mxbuild' in python_binary:
915969
is_graalpy = True
916-
gp_args = ["--vm.ea", "--vm.esa", "--experimental-options=true", "--python.EnableDebuggingBuiltins"]
970+
gp_args = ["--experimental-options=true", "--python.EnableDebuggingBuiltins"]
971+
if env.get("GRAALPYTEST_ALLOW_NO_JAVA_ASSERTIONS") != "true":
972+
gp_args += ["--vm.ea", "--vm.esa"]
917973
mx.log(f"Executable seems to be GraalPy, prepending arguments: {gp_args}")
918974
python_args += gp_args
919975
if is_graalpy and BYTECODE_DSL_INTERPRETER:
@@ -2562,4 +2618,5 @@ def run_downstream_test(args):
25622618
'graalpy-jmh': [graalpy_jmh, ''],
25632619
'deploy-local-maven-repo': [deploy_local_maven_repo_wrapper, ''],
25642620
'downstream-test': [run_downstream_test, ''],
2621+
'python-native-pgo': [graalpy_native_pgo_build_and_test, 'Build PGO-instrumented native image, run tests, then build PGO-optimized native image'],
25652622
})

0 commit comments

Comments
 (0)