Skip to content

Commit fa2b47b

Browse files
committed
"checkup" mode for benchmarks that checks GC activity and compilations
This mode adds necessary flags to the VM, doubles the iterations count, and then analyzes the output for exessive GC activity (>10% of iteration time), compilations finishing after the original iterations count, and warmup detected after the original iterations count.
1 parent c4be74a commit fa2b47b

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

mx.graalpython/mx_graalpython.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,14 @@
2727
import contextlib
2828
import datetime
2929
import glob
30+
import itertools
3031
import json
3132
import os
3233
import pathlib
3334
import platform
3435
import re
3536
import shlex
3637
import shutil
37-
38-
import itertools
3938
import sys
4039

4140
HPY_IMPORT_ORPHAN_BRANCH_NAME = "hpy-import"

mx.graalpython/mx_graalpython_benchmark.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ def get_extra_polyglot_args(self):
476476
class PythonBaseBenchmarkSuite(VmBenchmarkSuite, AveragingBenchmarkMixin):
477477
def __init__(self, name, benchmarks):
478478
super(PythonBaseBenchmarkSuite, self).__init__()
479+
self._checkup = 'GRAALPYTHON_BENCHMARKS_CHECKUP' in os.environ
479480
self._name = name
480481
self._benchmarks = benchmarks
481482
self._graph_dump_time = None
@@ -680,9 +681,15 @@ def _replace_host_vm(key):
680681
_replace_host_vm('graalvm-ee')
681682
self.post_run_graph(benchmarks[0], dims['host-vm-config'], dims['guest-vm-config'])
682683

684+
if self._checkup:
685+
self.checkup(out)
686+
683687
return ret_code, out, dims
684688

685689
def run(self, benchmarks, bm_suite_args):
690+
if '--checkup' in bm_suite_args:
691+
self._checkup = True
692+
bm_suite_args.remove('--checkup')
686693
results = super(PythonBaseBenchmarkSuite, self).run(benchmarks, bm_suite_args)
687694
self.addAverageAcrossLatestResults(results)
688695
return results
@@ -708,6 +715,10 @@ def postprocess_run_args(self, run_args):
708715
if arg.startswith("-i"):
709716
if len(run_args) >= i and run_args[i + 1] == "-1":
710717
pass
718+
elif self._checkup and len(run_args) >= i:
719+
iterations = int(run_args[i + 1]) * 2
720+
remaining = ["-i", str(iterations)] + run_args[i+2:]
721+
break
711722
else:
712723
remaining = run_args[i:]
713724
break
@@ -717,13 +728,78 @@ def postprocess_run_args(self, run_args):
717728

718729
if not (remaining and "-i" in remaining):
719730
iterations = DEFAULT_ITERATIONS + self.getExtraIterationCount(DEFAULT_ITERATIONS)
731+
if self._checkup:
732+
iterations *= 2
720733
remaining = ["-i", str(iterations)] + (remaining if remaining else [])
721734

735+
if self._checkup:
736+
vm_options += ['--engine.TraceCompilation', '-XX:+PrintGC']
737+
722738
return vm_options, remaining
723739

724740
def createCommandLineArgs(self, benchmarks, bmSuiteArgs):
725741
return self.createVmCommandLineArgs(benchmarks, bmSuiteArgs)
726742

743+
def checkup(self, out):
744+
lines = out.split('\n')
745+
benchmark_name = None
746+
current_iteration = -1
747+
iterations_count = -1
748+
iteration_times = []
749+
gc_times = []
750+
late_compilation = False
751+
for i in range(len(lines)):
752+
line = lines[i]
753+
754+
# this marks the beginning of an output of a benchmark
755+
benchmark_info = re.search("### (.*), \\d+ warmup iterations, (\\d+) bench iterations", line)
756+
if benchmark_name is None and benchmark_info:
757+
benchmark_name = benchmark_info.group(1)
758+
iterations_count = int(benchmark_info.group(2))
759+
mx.log(f"Checking benchmark {benchmark_name} with {iterations_count} iterations")
760+
continue
761+
762+
if benchmark_name is None:
763+
continue
764+
765+
# this marks the end of the processing of a single benchmark
766+
warmup_match = re.search("### WARMUP detected at iteration: (\\d+)", line)
767+
if warmup_match:
768+
warmup = int(warmup_match.group(1))
769+
for i in range(warmup, len(iteration_times)):
770+
if gc_times[i] > iteration_times[i] / 10:
771+
mx.warn(
772+
f"Benchmark checkup: {benchmark_name}: excessive GC pause of {gc_times[i]} (on {i} iteration)")
773+
if warmup > iterations_count / 2:
774+
mx.warn(f"Benchmark checkup: {benchmark_name}: warmup detected too late (on {warmup} iteration)")
775+
if late_compilation:
776+
mx.warn(
777+
f"Benchmark checkup: {benchmark_name}: compilation detected too late (on {late_compilation} iteration)")
778+
iteration_times = []
779+
gc_times = []
780+
current_iteration = -1
781+
benchmark_name = None
782+
late_compilation = False
783+
continue
784+
785+
# following is done only when we are inside benchmark output:
786+
iteration_info = re.search("### iteration=(\\d+), name=.*, duration=([0-9.]*)", line)
787+
if iteration_info:
788+
current_iteration += 1
789+
iteration_times += [float(iteration_info.group(2))]
790+
gc_times += [0.0]
791+
continue
792+
793+
if current_iteration == -1:
794+
continue
795+
796+
gc_log = re.search("\\[GC .* ([0-9,]*) secs]", line)
797+
if gc_log:
798+
gc_times[len(gc_times) - 1] += float(gc_log.group(1).replace(',', '.'))
799+
800+
if current_iteration >= iterations_count / 2 and "[engine] opt done" in line:
801+
late_compilation = current_iteration
802+
727803

728804
class PythonBenchmarkSuite(PythonBaseBenchmarkSuite):
729805
def __init__(self, name, bench_path, benchmarks, python_path=None):

0 commit comments

Comments
 (0)