Skip to content

Commit

Permalink
add CompileTheWorld to PolybenchLauncher
Browse files Browse the repository at this point in the history
  • Loading branch information
dougxc committed Jul 28, 2022
1 parent eaad7a2 commit ff36d60
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 38 deletions.
6 changes: 0 additions & 6 deletions compiler/mx.compiler/mx_graal_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,12 +502,6 @@ def group(self):
def subgroup(self):
return "graal-compiler"

def extraVmArgs(self):
if mx_compiler.isJDK8:
return ['-XX:-UseJVMCIClassLoader'] + super(JMHRunnerGraalCoreBenchmarkSuite, self).extraVmArgs()
else:
return super(JMHRunnerGraalCoreBenchmarkSuite, self).extraVmArgs()


mx_benchmark.add_bm_suite(JMHRunnerGraalCoreBenchmarkSuite())

Expand Down
2 changes: 1 addition & 1 deletion docs/mx.docs/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
"path": '.'
}
}
}
}
10 changes: 8 additions & 2 deletions vm/ci_common/common-bench.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,18 @@ local repo_config = import '../../repo-configuration.libsonnet';
notify_groups:: ['polybench'],
},

vm_bench_polybench_hpc_linux_common(env, metric, benchmarks='*'): self.vm_bench_polybench_linux_common(env=env) + self.polybench_hpc_linux_common + {
vm_bench_polybench_hpc_linux_common(env, metric, benchmarks='*', polybench_vm_config='native-interpreter'): self.vm_bench_polybench_linux_common(env=env) + self.polybench_hpc_linux_common + {
local machine_name = "x52", // restricting ourselves to x52 machines since we know hardware performance counters work properly there
machine_name_prefix:: "gate-",
capabilities+: [machine_name],
run+: [
self.base_cmd + ['benchmark', 'polybench:'+benchmarks, '--fork-count-file', 'ci_includes/polybench-hpc.json', '--results-file', self.result_file, '--machine-name', self.machine_name_prefix + machine_name, '--', '--polybench-vm-config', 'native-interpreter', '--metric='+metric],
self.base_cmd + ['benchmark', 'polybench:'+benchmarks,
'--fork-count-file', 'ci_includes/polybench-hpc.json',
'--results-file', self.result_file,
'--machine-name', self.machine_name_prefix + machine_name,
'--',
'--metric=' + metric,
'--polybench-vm-config=' + polybench_vm_config],
self.upload_and_wait_for_indexing + ['||', 'echo', 'Result upload failed!'],
],
},
Expand Down
30 changes: 28 additions & 2 deletions vm/mx.vm/mx_vm_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,11 @@ def version(self):
def benchmarkList(self, bmSuiteArgs):
if not hasattr(self, "_benchmarks"):
self._benchmarks = []
graal_test = mx.distribution('GRAAL_TEST', fatalIfMissing=False)
if graal_test:
# If the GRAAL_TEST distribution is available, the
# CompileTheWorld benchmark is available.
self._benchmarks = ['CompileTheWorld']
for group in ["interpreter", "compiler", "warmup", "nfi"]:
dir_path = os.path.join(self._get_benchmark_root(), group)
for f in os.listdir(dir_path):
Expand All @@ -991,8 +996,29 @@ def createCommandLineArgs(self, benchmarks, bmSuiteArgs):
if benchmarks is None or len(benchmarks) != 1:
mx.abort("Must specify one benchmark at a time.")
vmArgs = self.vmArgs(bmSuiteArgs)
benchmark_path = os.path.join(self._get_benchmark_root(), benchmarks[0])
return ["--path=" + benchmark_path] + vmArgs
benchmark = benchmarks[0]
if benchmark == 'CompileTheWorld':
# Run CompileTheWorld as a polybench benchmark, using instruction counting to get a stable metric.
# The CompileTheWorld class has been reorganized to have separate "prepare" and
# "compile" steps such that only the latter is measured by polybench.
# PAPI instruction counters are thread-local so CTW is run on the same thread as
# the polybench harness (i.e., CompileTheWorld.MultiThreaded=false).
import mx_compiler
res = mx_compiler._ctw_jvmci_export_args(arg_prefix='--vm.-') + [
'--ctw',
'--vm.cp=' + mx.distribution('GRAAL_ONLY_TEST').path + os.pathsep + mx.distribution('GRAAL_TEST').path,
'--vm.DCompileTheWorld.MaxCompiles=10000',
'--vm.DCompileTheWorld.Classpath=' + mx.library('DACAPO_MR1_BACH').get_path(resolve=True),
'--vm.DCompileTheWorld.Verbose=false',
'--vm.DCompileTheWorld.MultiThreaded=false',
'--vm.Dlibgraal.ShowConfiguration=info',
'--metric=instructions',
'-w', '1',
'-i', '5'] + vmArgs
else:
benchmark_path = os.path.join(self._get_benchmark_root(), benchmark)
res = ["--path=" + benchmark_path] + vmArgs
return res

def get_vm_registry(self):
return _polybench_vm_registry
Expand Down
4 changes: 4 additions & 0 deletions vm/mx.vm/polybench-ctw-ce
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DYNAMIC_IMPORTS=/compiler,/sdk,/substratevm,/truffle
COMPONENTS=cmp,icu4j,lg,ni,nil,pbm,pmh,pbi,sdk,svm,svmnfi,svmsl,tfl,tflm
NATIVE_IMAGES=lib:jvmcicompiler
DISABLE_INSTALLABLES=False
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class Config {
Mode mode;
Metric metric;
boolean evalSourceOnlyDefault;
boolean compileTheWorld;

final List<String> unrecognizedArguments = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -101,6 +102,7 @@ static class ArgumentParser {
this.consumers.add(new ArgumentConsumer("--class-name", (value, config) -> config.className = value));
this.consumers.add(new ArgumentConsumer("--mode", (value, config) -> config.mode = Config.Mode.parse(value)));
this.consumers.add(new ArgumentConsumer("--metric", (value, config) -> (new MetricFactory()).loadMetric(config, value)));
this.consumers.add(new ArgumentConsumer("--ctw", (value, config) -> config.compileTheWorld = true));
this.consumers.add(new ArgumentConsumer("-w", (value, config) -> config.warmupIterations = Integer.parseInt(value)));
this.consumers.add(new ArgumentConsumer("-i", (value, config) -> config.iterations = Integer.parseInt(value)));
this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> config.initMultiEngine().sharedEngine = Boolean.parseBoolean(value)));
Expand Down Expand Up @@ -224,31 +226,37 @@ private void processMultiContextArguments() {
}
}

// Parse engine options and store them to config.engineOptions
HashMap<String, String> polyglotOptions = new HashMap<>();
parseUnrecognizedOptions(getLanguageId(config.path), polyglotOptions, engineOptions);
if (!polyglotOptions.isEmpty()) {
config.initMultiEngine().engineOptions.putAll(polyglotOptions);
}
// Parse run specific options and store them to config.runOptionsMap
for (Map.Entry<Integer, List<String>> runOptionsEntry : runOptionsMap.entrySet()) {
Map<String, String> runOptions = config.initMultiEngine().polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>());
if (!runOptionsEntry.getValue().isEmpty()) {
if (useExperimental) {
// the enabled experimental-options flag must be propagated to runOptions to
// enable
// parsing of run-level experimental options
runOptionsEntry.getValue().add("--experimental-options");
if (!config.compileTheWorld) {
// Parse engine options and store them to config.engineOptions
HashMap<String, String> polyglotOptions = new HashMap<>();
parseUnrecognizedOptions(getLanguageId(config.path), polyglotOptions, engineOptions);
if (!polyglotOptions.isEmpty()) {
config.initMultiEngine().engineOptions.putAll(polyglotOptions);
}
// Parse run specific options and store them to config.runOptionsMap
for (Map.Entry<Integer, List<String>> runOptionsEntry : runOptionsMap.entrySet()) {
Map<String, String> runOptions = config.initMultiEngine().polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>());
if (!runOptionsEntry.getValue().isEmpty()) {
if (useExperimental) {
// the enabled experimental-options flag must be propagated to runOptions to
// enable
// parsing of run-level experimental options
runOptionsEntry.getValue().add("--experimental-options");
}
parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue());
}
parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue());
}
}
}

@Override
protected void validateArguments(Map<String, String> polyglotOptions) {
if (config.path == null) {
throw abort("Must specify path to the source file with --path.");
if (!config.compileTheWorld) {
throw abort("Must specify path to the source file with --path.");
}
} else if (config.compileTheWorld) {
throw abort("--ctw does not support --path.");
}
try {
config.metric.validateConfig(config, polyglotOptions);
Expand Down Expand Up @@ -348,6 +356,20 @@ String getLanguageId(String path) {
}

private EvalResult evalSource(Context context) {
if (config.compileTheWorld) {
try {
Class<?> ctwClass = Class.forName("org.graalvm.compiler.hotspot.test.CompileTheWorld");
Method createMethod = ctwClass.getDeclaredMethod("create");
Method prepareMethod = ctwClass.getDeclaredMethod("prepare");
Object ctw = createMethod.invoke(null);
Object compilations = prepareMethod.invoke(ctw);
Object[] ctwArgs = {ctw, compilations};
return new EvalResult("jvm", "CompileTheWorld", true, 0, ctwArgs);
} catch (Exception e) {
throw new AssertionError("Error creating CompileTheWorld object", e);
}
}

final String path = config.path;
final String language = getLanguageId(config.path);

Expand Down Expand Up @@ -412,9 +434,9 @@ static class EvalResult {
final String sourceName;
final boolean isBinarySource;
final long sourceLength;
final Value value;
final Object value;

EvalResult(String languageId, String sourceName, boolean isBinarySource, long sourceLength, Value value) {
EvalResult(String languageId, String sourceName, boolean isBinarySource, long sourceLength, Object value) {
this.languageId = languageId;
this.sourceName = sourceName;
this.isBinarySource = isBinarySource;
Expand All @@ -434,7 +456,7 @@ private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly,
contextBuilder.logHandler(handler);
}

String extension = getExtension(config.path);
String extension = config.path == null ? null : getExtension(config.path);
if (extension != null) {
switch (extension) {
// Set Java class path before spawning context.
Expand Down Expand Up @@ -469,8 +491,11 @@ private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly,
log("");

log("::: Bench specific options :::");
config.parseBenchSpecificDefaults(evalResult.value);
config.metric.parseBenchSpecificOptions(evalResult.value);
if (evalResult.value instanceof Value) {
Value value = (Value) evalResult.value;
config.parseBenchSpecificDefaults(value);
config.metric.parseBenchSpecificOptions(value);
}
log(config.toString());

log("Initialization completed.");
Expand Down Expand Up @@ -506,7 +531,7 @@ private static String round(double v) {
return String.format("%.2f", v);
}

private void repeatIterations(Context context, String languageId, String name, Value evalSource, boolean warmup, int iterations) {
private void repeatIterations(Context context, String languageId, String name, Object evalSource, boolean warmup, int iterations) {
Workload workload = lookup(context, languageId, evalSource, "run");
// Enter explicitly to avoid context switches for each iteration.
context.enter();
Expand Down Expand Up @@ -536,7 +561,29 @@ private void repeatIterations(Context context, String languageId, String name, V
}
}

private Workload lookup(Context context, String languageId, Value evalSource, String memberName) {
private Workload lookup(Context context, String languageId, Object evalSource, String memberName) {
if (this.config.compileTheWorld) {
// to stub out
return new Workload() {
@Override
public void run() {
Object[] ctwArgs = (Object[]) evalSource;
Object ctw = ctwArgs[0];
Object compilations = ctwArgs[1];
try {
Method compileMethod = ctw.getClass().getDeclaredMethod("compile", compilations.getClass());
compileMethod.invoke(ctw, compilations);

// Force a GC to encourage reclamation of nmethods when their InstalledCode
// reference has been dropped.
System.gc();
} catch (Exception e) {
throw new AssertionError(e);
}
}
};
}
Value evalSourceValue = (Value) evalSource;
Value result;
// language-specific lookup
switch (languageId) {
Expand All @@ -547,11 +594,11 @@ private Workload lookup(Context context, String languageId, Value evalSource, St
case "java":
// Espresso doesn't provide methods as executable values.
// It can only invoke methods from the declaring class or receiver.
return Workload.createInvoke(evalSource, "main", ProxyArray.fromArray());
return Workload.createInvoke(evalSourceValue, "main", ProxyArray.fromArray());
default:
// first try the memberName directly
if (evalSource.hasMember(memberName)) {
result = evalSource.getMember(memberName);
if (evalSourceValue.hasMember(memberName)) {
result = evalSourceValue.getMember(memberName);
} else {
// Fallback for other languages: Look for 'memberName' in global scope.
result = context.getBindings(languageId).getMember(memberName);
Expand Down

0 comments on commit ff36d60

Please sign in to comment.