2323# OF THE POSSIBILITY OF SUCH DAMAGE.
2424from __future__ import print_function
2525
26+ import itertools
2627import functools
2728import statistics
2829import sys
5455# constants
5556#
5657# ----------------------------------------------------------------------------------------------------------------------
57- ENV_PYPY_HOME = "PYPY_HOME"
58- ENV_PYTHON3_HOME = "PYTHON3_HOME"
59- ENV_VIRTUAL_ENV = "VIRTUAL_ENV"
60- ENV_JYTHON_JAR = "JYTHON_JAR"
6158VM_NAME_GRAALPYTHON = "graalpython"
62- VM_NAME_CPYTHON = "cpython"
63- VM_NAME_PYPY = "pypy"
64- VM_NAME_JYTHON = "jython"
6559VM_NAME_GRAALPYTHON_SVM = "graalpython-svm"
6660GROUP_GRAAL = "Graal"
6761SUBGROUP_GRAAL_PYTHON = "graalpython"
@@ -129,12 +123,11 @@ def _handle_var(key_value):
129123#
130124# ----------------------------------------------------------------------------------------------------------------------
131125class AbstractPythonVm (OutputCapturingVm , ABC ):
132- def __init__ (self , name , config_name , options = None , env = None ):
126+ def __init__ (self , name , config_name , options = None ):
133127 super ().__init__ ()
134128 self ._name = name
135129 self ._config_name = config_name
136130 self ._options = options
137- self ._env = env
138131
139132 @property
140133 def options (self ):
@@ -153,21 +146,21 @@ def interpreter(self):
153146 def post_process_command_line_args (self , args ):
154147 return args
155148
156- def run_vm (self , args , out = None , err = None , cwd = None , nonZeroIsFatal = False ):
149+ def run_vm (self , args , out = None , err = None , cwd = None , nonZeroIsFatal = False , env = None ):
157150 mx .logv (shlex .join ([self .interpreter ] + args ))
158151 return mx .run (
159152 [self .interpreter ] + args ,
160153 out = out ,
161154 err = err ,
162155 cwd = cwd ,
163156 nonZeroIsFatal = nonZeroIsFatal ,
164- env = self . _env
157+ env = env ,
165158 )
166159
167160
168161class AbstractPythonIterationsControlVm (AbstractPythonVm ):
169- def __init__ (self , name , config_name , options = None , env = None , iterations = None ):
170- super ().__init__ (name , config_name , options = options , env = env )
162+ def __init__ (self , name , config_name , options = None , iterations = None ):
163+ super ().__init__ (name , config_name , options = options )
171164 try :
172165 self ._iterations = int (iterations )
173166 except :
@@ -194,10 +187,8 @@ def run_vm(self, args, *splat, **kwargs):
194187
195188
196189class CPythonVm (AbstractPythonIterationsControlVm ):
197- PYTHON_INTERPRETER = "python3"
198-
199- def __init__ (self , config_name , options = None , env = None , virtualenv = None , iterations = 0 ):
200- super ().__init__ (VM_NAME_CPYTHON , config_name , options = options , env = env , iterations = iterations )
190+ def __init__ (self , config_name , options = None , virtualenv = None , iterations = 0 ):
191+ super ().__init__ ("cpython" , config_name , options = options , iterations = iterations )
201192 self ._virtualenv = virtualenv
202193
203194 def override_iterations (self , requested_iterations ):
@@ -206,41 +197,74 @@ def override_iterations(self, requested_iterations):
206197
207198 @property
208199 def interpreter (self ):
209- venv = self ._virtualenv if self ._virtualenv else mx .get_env (ENV_VIRTUAL_ENV )
210- if venv :
211- mx .log (f"CPythonVM virtualenv={ venv } " )
212- return os .path .join (venv , 'bin' , CPythonVm .PYTHON_INTERPRETER )
213- home = mx .get_env (ENV_PYTHON3_HOME )
214- if home :
215- mx .log (f"CPythonVM python3 home={ home } " )
216- return os .path .join (home , CPythonVm .PYTHON_INTERPRETER )
217- return CPythonVm .PYTHON_INTERPRETER
200+ candidates_pre = [
201+ self ._virtualenv ,
202+ mx .get_env ("VIRTUAL_ENV" ),
203+ mx .get_env ("PYTHON3_HOME" ),
204+ ]
205+ candidates_suf = [
206+ join ("bin" , "python3" ),
207+ join ("bin" , "python" ),
208+ "python3" ,
209+ "python" ,
210+ sys .executable ,
211+ ]
212+ for p , s in itertools .product (candidates_pre , candidates_suf ):
213+ if os .path .exists (exe := os .path .join (p or "" , s )):
214+ mx .log (f"CPython VM { exe = } " )
215+ return exe
216+ assert False , "sys.executable should really exist"
218217
218+ def run_vm (self , args , * splat , ** kwargs ):
219+ for idx , arg in enumerate (args ):
220+ if "--vm.Xmx" in arg :
221+ mx .warn (f"Ignoring { arg } , cannot restrict memory on CPython." )
222+ args = args [:idx ] + args [idx + 1 :]
223+ break
224+ return super ().run_vm (args , * splat , ** kwargs )
219225
220- class PyPyVm (AbstractPythonIterationsControlVm ):
221- PYPY_INTERPRETER = "pypy3"
222226
223- def __init__ (self , config_name , options = None , env = None , virtualenv = None , iterations = 0 ):
224- super ().__init__ (VM_NAME_PYPY , config_name , options = options , env = env , iterations = iterations )
227+ class PyPyVm (AbstractPythonIterationsControlVm ):
228+ def __init__ (self , config_name , options = None , virtualenv = None , iterations = 0 ):
229+ super ().__init__ ("pypy" , config_name , options = options , iterations = iterations )
225230
226231 def override_iterations (self , requested_iterations ):
227232 # PyPy warms up much faster, half should be enough
228233 return int (requested_iterations / 2 )
229234
230235 @property
231236 def interpreter (self ):
232- home = mx .get_env (ENV_PYPY_HOME )
233- if not home :
237+ if home := mx .get_env ("PYPY_HOME" ):
238+ exe = join (home , "bin" , "pypy3" )
239+ else :
234240 try :
235- return subprocess .check_output ("which %s" % PyPyVm . PYPY_INTERPRETER , shell = True ).decode ().strip ()
241+ exe = subprocess .check_output ("which pypy3" , shell = True ).decode ().strip ()
236242 except OSError :
237- mx .abort ("{} is not set!" .format (ENV_PYPY_HOME ))
238- return join (home , 'bin' , PyPyVm .PYPY_INTERPRETER )
243+ mx .abort ("PYPY_HOME is not set!" )
244+ mx .log (f"PyPy { exe = } " )
245+ return exe
246+
247+ def run_vm (self , args , * splat , env = None , ** kwargs ):
248+ env = env or os .environ .copy ()
249+ xmxArg = re .compile ("--vm.Xmx([0-9]+)([kKgGmM])" )
250+ pypyGcMax = "8GB"
251+ for idx , arg in enumerate (args ):
252+ if m := xmxArg .search (arg ):
253+ args = args [:idx ] + args [idx + 1 :]
254+ pypyGcMax = f"{ m .group (1 )} { m .group (2 ).upper ()} B"
255+ mx .log (f"Setting PYPY_GC_MAX={ pypyGcMax } via { arg } " )
256+ break
257+ else :
258+ mx .log (
259+ f"Setting PYPY_GC_MAX={ pypyGcMax } , use --vm.Xmx argument to override it"
260+ )
261+ env ["PYPY_GC_MAX" ] = pypyGcMax
262+ return super ().run_vm (args , * splat , env = env , ** kwargs )
239263
240264
241265class GraalPythonVm (AbstractPythonIterationsControlVm ):
242- def __init__ (self , config_name , options = None , env = None , virtualenv = None , iterations = None , extra_polyglot_args = None ):
243- super ().__init__ (VM_NAME_GRAALPYTHON , config_name , options = options , env = env , iterations = iterations )
266+ def __init__ (self , config_name , options = None , virtualenv = None , iterations = None , extra_polyglot_args = None ):
267+ super ().__init__ (VM_NAME_GRAALPYTHON , config_name , options = options , iterations = iterations )
244268 self ._extra_polyglot_args = extra_polyglot_args or []
245269
246270 @property
@@ -273,7 +297,7 @@ def extract_vm_info(self, args=None):
273297 out_version = subprocess .check_output ([self .interpreter , '--version' ], universal_newlines = True )
274298 # The benchmark data goes back a ways, we modify the reported dims for
275299 # continuity with the historical queries
276- graalvm_version_match = re .search (r"\(([^\)]+ ((?:\d+\.?)+))\)" , out_version )
300+ graalvm_version_match = re .search (r"\(([^\)]+ ((?:\d+\.?)+)).* \)" , out_version )
277301 if not graalvm_version_match :
278302 mx .log (f"Using { out_version } as platform version string input" )
279303 graalvm_version_match = [out_version , out_version , out_version ]
@@ -311,15 +335,14 @@ def get_extra_polyglot_args(self):
311335
312336class GraalPythonJavaDriverVm (GuestVm ):
313337 def __init__ (self , config_name = CONFIGURATION_DEFAULT , cp_suffix = None , distributions = None , cp_prefix = None ,
314- host_vm = None , extra_vm_args = None , extra_polyglot_args = None , env = None ):
338+ host_vm = None , extra_vm_args = None , extra_polyglot_args = None ):
315339 super ().__init__ (host_vm = host_vm )
316340 self ._config_name = config_name
317341 self ._distributions = distributions or ['GRAALPYTHON_BENCH' ]
318342 self ._cp_suffix = cp_suffix
319343 self ._cp_prefix = cp_prefix
320344 self ._extra_vm_args = extra_vm_args
321345 self ._extra_polyglot_args = extra_polyglot_args if isinstance (extra_polyglot_args , list ) else []
322- self ._env = env
323346
324347 def name (self ):
325348 return VM_NAME_GRAALPYTHON
@@ -341,30 +364,30 @@ def get_classpath(self):
341364 def with_host_vm (self , host_vm ):
342365 return self .__class__ (config_name = self ._config_name , distributions = self ._distributions ,
343366 cp_suffix = self ._cp_suffix , cp_prefix = self ._cp_prefix , host_vm = host_vm ,
344- extra_vm_args = self ._extra_vm_args , extra_polyglot_args = self ._extra_polyglot_args ,
345- env = self ._env )
367+ extra_vm_args = self ._extra_vm_args , extra_polyglot_args = self ._extra_polyglot_args )
346368
347369 def launcher_class (self ):
348370 return 'com.oracle.graal.python.benchmarks.JavaBenchmarkDriver'
349371
350372 def run (self , cwd , args ):
351373 extra_polyglot_args = self .get_extra_polyglot_args ()
352374 host_vm = self .host_vm ()
353- with environ (self ._env or {}):
354- cp = self .get_classpath ()
355- jhm = mx .dependency ("mx:JMH_1_21" )
356- cp_deps = [
357- mx .distribution ('GRAALPYTHON_BENCH' , fatalIfMissing = True ),
358- jhm ,
359- mx .dependency ("sdk:LAUNCHER_COMMON" )
360- ] + jhm .deps
361- cp += [x .classpath_repr () for x in cp_deps ]
362- java_args = ['-cp' , ':' .join (cp )] + [self .launcher_class ()]
363- out = mx .TeeOutputCapture (mx .OutputCapture ())
364- code = host_vm .run_java (java_args + extra_polyglot_args + args , cwd = cwd , out = out , err = out )
365- out = out .underlying .data
366- dims = host_vm .dimensions (cwd , args , code , out )
367- return code , out , dims
375+ cp = self .get_classpath ()
376+ jhm = mx .dependency ("mx:JMH_1_21" )
377+ cp_deps = mx .classpath_entries (filter (None , [
378+ mx .distribution ('GRAALPYTHON_BENCH' , fatalIfMissing = True ),
379+ mx .distribution ('TRUFFLE_RUNTIME' , fatalIfMissing = True ),
380+ mx .distribution ('TRUFFLE_ENTERPRISE' , fatalIfMissing = False ),
381+ jhm ,
382+ mx .dependency ("sdk:LAUNCHER_COMMON" )
383+ ] + jhm .deps ))
384+ cp += [x .classpath_repr () for x in cp_deps ]
385+ java_args = ['-cp' , ':' .join (cp )] + [self .launcher_class ()]
386+ out = mx .TeeOutputCapture (mx .OutputCapture ())
387+ code = host_vm .run_java (java_args + extra_polyglot_args + args , cwd = cwd , out = out , err = out )
388+ out = out .underlying .data
389+ dims = host_vm .dimensions (cwd , args , code , out )
390+ return code , out , dims
368391
369392 def get_extra_polyglot_args (self ):
370393 return ["--experimental-options" , "--python.MaxNativeMemory=%s" % (2 ** 34 ), * self ._extra_polyglot_args ]
@@ -381,7 +404,7 @@ def get_extra_polyglot_args(self):
381404
382405class PythonBaseBenchmarkSuite (VmBenchmarkSuite , AveragingBenchmarkMixin ):
383406 def __init__ (self , name , benchmarks ):
384- super (PythonBaseBenchmarkSuite , self ).__init__ ()
407+ super ().__init__ ()
385408 self ._checkup = 'GRAALPYTHON_BENCHMARKS_CHECKUP' in os .environ
386409 self ._name = name
387410 self ._benchmarks = benchmarks
@@ -578,14 +601,7 @@ def rules(self, output, benchmarks, bm_suite_args):
578601 ]
579602
580603 def runAndReturnStdOut (self , benchmarks , bmSuiteArgs ):
581- ret_code , out , dims = super (PythonBaseBenchmarkSuite , self ).runAndReturnStdOut (benchmarks , bmSuiteArgs )
582-
583- # host-vm rewrite rules
584- if dims ['host-vm' ] not in ('graalvm-ce' , 'graalvm-ee' ):
585- if mx .suite ('graal-enterprise' , fatalIfMissing = False ):
586- dims ['host-vm' ] = 'graalvm-ee'
587- else :
588- dims ['host-vm' ] = 'graalvm-ce'
604+ ret_code , out , dims = super ().runAndReturnStdOut (benchmarks , bmSuiteArgs )
589605
590606 self .post_run_graph (benchmarks [0 ], dims ['host-vm-config' ], dims ['guest-vm-config' ])
591607
@@ -598,7 +614,7 @@ def run(self, benchmarks, bm_suite_args):
598614 if '--checkup' in bm_suite_args :
599615 self ._checkup = True
600616 bm_suite_args .remove ('--checkup' )
601- results = super (PythonBaseBenchmarkSuite , self ).run (benchmarks , bm_suite_args )
617+ results = super ().run (benchmarks , bm_suite_args )
602618 self .addAverageAcrossLatestResults (results )
603619 return results
604620
@@ -710,7 +726,7 @@ def checkup(self, out):
710726
711727class PythonBenchmarkSuite (PythonBaseBenchmarkSuite ):
712728 def __init__ (self , name , bench_path , benchmarks , python_path = None ):
713- super (PythonBenchmarkSuite , self ).__init__ (name , benchmarks )
729+ super ().__init__ (name , benchmarks )
714730 self ._python_path = python_path
715731 self ._harness_path = HARNESS_PATH
716732 self ._harness_path = join (SUITE .dir , self ._harness_path )
@@ -778,7 +794,7 @@ def get_benchmark_suites(cls, benchmarks):
778794
779795class PythonJavaEmbeddingBenchmarkSuite (PythonBaseBenchmarkSuite ):
780796 def __init__ (self , name , bench_path , benchmarks ):
781- super (PythonJavaEmbeddingBenchmarkSuite , self ).__init__ (name , benchmarks )
797+ super ().__init__ (name , benchmarks )
782798 self ._bench_path = bench_path
783799
784800 def get_vm_registry (self ):
@@ -1001,6 +1017,9 @@ def register_vms(suite, sandboxed_options):
10011017 # Other Python VMs:
10021018 python_vm_registry .add_vm (CPythonVm (config_name = CONFIGURATION_DEFAULT ), suite )
10031019 python_vm_registry .add_vm (PyPyVm (config_name = CONFIGURATION_DEFAULT ), suite )
1020+ # For continuity with old datapoints, provide CPython and PyPy with launcher config_name
1021+ python_vm_registry .add_vm (CPythonVm (config_name = "launcher" ), suite )
1022+ python_vm_registry .add_vm (PyPyVm (config_name = "launcher" ), suite )
10041023
10051024 graalpy_vms = []
10061025
0 commit comments