@@ -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+
280324def 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