diff --git a/common.json b/common.json index 5362cbedaf05..366f532f95b0 100644 --- a/common.json +++ b/common.json @@ -45,13 +45,13 @@ "labsjdk-ee-21-llvm": {"name": "labsjdk", "version": "ee-21.0.2+13-jvmci-23.1-b33-sulong", "platformspecific": true }, "graalvm-ee-21": {"name": "graalvm-java21", "version": "23.1.3", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "23", "build_id": "jdk-23+23", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-23+23-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-23+23-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-23+23-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-23+23-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-23+23-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-23+23-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "23", "build_id": "jdk-23+24", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-23+24-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-23+24-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-23+24-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-23+24-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-23+24-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-23+24-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java index b1fb2190a0d0..1f5006207bc1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java @@ -26,9 +26,10 @@ import java.util.Arrays; +import jdk.graal.compiler.core.common.PermanentBailoutException; +import jdk.graal.compiler.core.common.util.EventCounter.EventCounterMarker; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.TTY; -import jdk.graal.compiler.core.common.PermanentBailoutException; import jdk.graal.compiler.graph.Graph; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; @@ -195,8 +196,8 @@ private static void overflowAction(OptionValues opt, EventCounter counter) { * hang and throw a bailout. */ private static void assertProgress(OptionValues opt, EventCounter counter) { - final EventCounter lastCounter = lastCounterForThread.get(); - if (lastCounter != null && !lastCounter.equals(counter)) { + final EventCounterMarker lastMarker = lastMarkerForThread.get(); + if (lastMarker != null && lastMarker != counter.getEventCounterMarker()) { resetProgressDetection(); return; } @@ -231,9 +232,9 @@ private static void assertProgress(OptionValues opt, EventCounter counter) { if (lastStackTrace == null || lastStackTrace.length != currentStackTrace.length || !Arrays.equals(lastStackTrace, currentStackTrace)) { lastStackTraceForThread.set(currentStackTrace); lastUniqueStackTraceForThreadMS.set(System.currentTimeMillis()); - lastCounterForThread.set(counter); + lastMarkerForThread.set(counter.getEventCounterMarker()); } else { - assertProgressSlowPath(opt, lastStackTrace, lastCounter, currentStackTrace); + assertProgressSlowPath(opt, lastStackTrace, counter, currentStackTrace); } } @@ -243,7 +244,7 @@ private static void assertProgressNoTracking(OptionValues opt, EventCounter coun * n seconds */ lastUniqueStackTraceForThreadMS.set(System.currentTimeMillis()); - lastCounterForThread.set(counter); + lastMarkerForThread.set(counter.getEventCounterMarker()); noProgressStartPeriodMS.set((long) (Options.CompilationNoProgressStartTrackingProgressPeriod.getValue(opt) * 1000)); if (LOG_PROGRESS_DETECTION) { @@ -251,7 +252,7 @@ private static void assertProgressNoTracking(OptionValues opt, EventCounter coun } } - private static void assertProgressSlowPath(OptionValues opt, StackTraceElement[] lastStackTrace, EventCounter lastCounter, StackTraceElement[] currentStackTrace) { + private static void assertProgressSlowPath(OptionValues opt, StackTraceElement[] lastStackTrace, EventCounter counter, StackTraceElement[] currentStackTrace) { /* * We perform this check inside here since its cheaper to take the last stack trace (last * will be null for the first in the current compile) than actually checking the option @@ -276,24 +277,31 @@ private static void assertProgressSlowPath(OptionValues opt, StackTraceElement[] if (LOG_PROGRESS_DETECTION) { TTY.printf("CompilationAlarm: Progress detection %s; no progress for %d ms; stuck? %s; stuck threshold %d ms%n", - lastCounter, elapsed, stuck, stuckThreshold); + counter, elapsed, stuck, stuckThreshold); } if (stuck) { throw new PermanentBailoutException("Observed identical stack traces for %d ms, indicating a stuck compilation, counter = %s, stack is:%n%s", - elapsed, lastCounter, Util.toString(lastStackTrace)); + elapsed, counter, Util.toString(lastStackTrace)); } } public static void resetProgressDetection() { lastStackTraceForThread.set(null); lastUniqueStackTraceForThreadMS.set(null); - lastCounterForThread.set(null); + lastMarkerForThread.set(null); noProgressStartPeriodMS.set(null); } private static final ThreadLocal lastStackTraceForThread = new ThreadLocal<>(); private static final ThreadLocal lastUniqueStackTraceForThreadMS = new ThreadLocal<>(); - private static final ThreadLocal lastCounterForThread = new ThreadLocal<>(); + /** + * Note that all these thread locals are not necessarily reset for a while even if worker + * threads have moved on to do actual work (but just not compiling graphs). Especially in the + * native image generator, not all {@link #assertProgress} calls can be in a closeable scope + * that invokes {@link #resetProgressDetection}. It is therefore critical that they do not keep + * large data structures like actual Graal graphs or LIR alive. + */ + private static final ThreadLocal lastMarkerForThread = new ThreadLocal<>(); private static final ThreadLocal noProgressStartPeriodMS = new ThreadLocal<>(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/EventCounter.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/EventCounter.java index 7d364eb9d8f9..cafe91c33048 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/EventCounter.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/EventCounter.java @@ -29,6 +29,19 @@ */ public interface EventCounter { + /** + * A shallow marker that can be kept alive by {@link CompilationAlarm} without keeping large + * data structures (the actual {@link EventCounter} implementation classes) alive. + */ + final class EventCounterMarker { + } + + /** + * Returns the unique marker object for this event counter. This object is used by + * {@link CompilationAlarm} to check for progress. + */ + EventCounterMarker getEventCounterMarker(); + /** * Increment the current counter and determine if it overflows max and reset it if so. Users of * this class typically take some action if an overflow happens. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Graph.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Graph.java index d2e7a85ea529..65df8881df73 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Graph.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Graph.java @@ -182,6 +182,12 @@ public int hashCode(Object k) { * used to trigger certain operations. */ private int eventCounter; + private final EventCounterMarker eventCounterMarker = new EventCounterMarker(); + + @Override + public EventCounterMarker getEventCounterMarker() { + return eventCounterMarker; + } @Override public boolean eventCounterOverflows(int max) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 201f9503e533..cb662be9ea80 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -55,8 +55,8 @@ public final class JVMCIVersionCheck { private static final Map> JVMCI_MIN_VERSIONS = Map.of( "21", Map.of(DEFAULT_VENDOR_ENTRY, createLegacyVersion(23, 1, 33)), "23", Map.of( - "Oracle Corporation", createLabsJDKVersion("23+23", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("23+23", 1))); + "Oracle Corporation", createLabsJDKVersion("23+24", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("23+24", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIR.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIR.java index 0176aeb6c88c..4b1467285340 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIR.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIR.java @@ -82,6 +82,7 @@ public final class LIR extends LIRGenerator.VariableProvider implements EventCou * to trigger certain operations. */ private int eventCounter; + private final EventCounterMarker eventCounterMarker = new EventCounterMarker(); /** * Creates a new LIR instance for the specified compilation. @@ -98,6 +99,11 @@ public LIR(AbstractControlFlowGraph cfg, this.debug = debug; } + @Override + public EventCounterMarker getEventCounterMarker() { + return eventCounterMarker; + } + @Override public boolean eventCounterOverflows(int max) { if (eventCounter++ > max) { diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py deleted file mode 100644 index bfba48dff5a4..000000000000 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ /dev/null @@ -1,1981 +0,0 @@ -# -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -import sys -import re -import argparse -import os -from os.path import join, exists -import json -import shutil -from shutil import rmtree -from tempfile import mkdtemp, mkstemp - -import mx -import mx_benchmark -from mx_benchmark import ParserEntry, DataPoints -import mx_sdk_benchmark -from mx_sdk_benchmark import NativeImageBundleBasedBenchmarkMixin -import mx_sdk_vm_impl - -_suite = mx.suite('java-benchmarks') - - -from configparser import ConfigParser -from io import StringIO - - -def _configparser_read_file(configp, fp): - configp.read_file(fp) - - -# Short-hand commands used to quickly run common benchmarks. -mx.update_commands(_suite, { - 'dacapo': [ - lambda args: createBenchmarkShortcut("dacapo", args), - '[|*] [-- [VM options] [-- [DaCapo options]]]' - ], - 'scaladacapo': [ - lambda args: createBenchmarkShortcut("scala-dacapo", args), - '[|*] [-- [VM options] [-- [Scala DaCapo options]]]' - ], - 'specjvm2008': [ - lambda args: createBenchmarkShortcut("specjvm2008", args), - '[|*] [-- [VM options] [-- [SPECjvm2008 options]]]' - ], - 'specjbb2015': [ - lambda args: mx_benchmark.benchmark(["specjbb2015"] + args), - '[-- [VM options] [-- [SPECjbb2015 options]]]' - ], - 'renaissance': [ - lambda args: createBenchmarkShortcut("renaissance", args), - '[|*] [-- [VM options] [-- [Renaissance options]]]' - ], - 'shopcart': [ - lambda args: createBenchmarkShortcut("shopcart", args), - '[-- [VM options] [-- [ShopCart options]]]' - ], - 'awfy': [ - lambda args: createBenchmarkShortcut("awfy", args), - '[|*] [-- [VM options] ] [-- [AWFY options] ]]' - ], -}) - - -def createBenchmarkShortcut(benchSuite, args): - if not args: - benchname = "*" - remaining_args = [] - elif args[0] == "--": - # not a benchmark name - benchname = "*" - remaining_args = args - else: - benchname = args[0] - remaining_args = args[1:] - return mx_benchmark.benchmark([benchSuite + ":" + benchname] + remaining_args) - - -# Adds a java VM from JAVA_HOME without any assumption about it -mx_benchmark.add_java_vm(mx_benchmark.DefaultJavaVm('java-home', 'default'), _suite, 1) - - -def java_home_jdk(): - return mx.get_jdk() - - -class BaseMicroserviceBenchmarkSuite(mx_benchmark.BenchmarkSuite): - def group(self): - return "Graal" - - def subgroup(self): - return "graal-compiler" - - def validateReturnCode(self, retcode): - return retcode == 143 - - def applicationDist(self): - raise NotImplementedError() - - def applicationPath(self): - raise NotImplementedError() - - def applicationStartupRule(self, benchSuiteName, benchmark): - return [ - # Example of Micronaut startup log: - # "[main] INFO io.micronaut.runtime.Micronaut - Startup completed in 328ms. Server Running: " - mx_benchmark.StdOutRule( - self.get_application_startup_regex(), - { - "benchmark": benchmark, - "bench-suite": benchSuiteName, - "metric.name": "app-startup", - "metric.value": ("", float), - "metric.unit": self.get_application_startup_units(), - "metric.better": "lower", - } - ) - ] - - def get_application_startup_regex(self): - raise NotImplementedError() - - def get_application_startup_units(self): - raise NotImplementedError - - def skip_agent_assertions(self, benchmark, args): - # This method overrides NativeImageMixin.skip_agent_assertions - user_args = super(BaseMicroserviceBenchmarkSuite, self).skip_agent_assertions(benchmark, args) - if user_args is not None: - return user_args - else: - return [] - - def default_stages(self): - # This method is used by NativeImageMixin.stages - raise NotImplementedError() - - -class BaseSpringBenchmarkSuite(BaseMicroserviceBenchmarkSuite, NativeImageBundleBasedBenchmarkMixin): - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - return self.create_bundle_command_line_args(benchmarks, bmSuiteArgs) - - def get_application_startup_regex(self): - # Example of SpringBoot 3 startup log: - # 2023-05-16T14:08:54.033+02:00 INFO 24381 --- [ main] o.s.s.petclinic.PetClinicApplication : Started PetClinicApplication in 3.774 seconds (process running for 4.1) - return r"Started [^ ]+ in (?P\d*[.,]?\d*) seconds \(process running for (?P\d*[.,]?\d*)\)$" - - def get_application_startup_units(self): - return 's' - - def get_image_env(self): - # Disable experimental option checking. - return {**os.environ, "NATIVE_IMAGE_EXPERIMENTAL_OPTIONS_ARE_FATAL": "false"} - - def default_stages(self): - return ['instrument-image', 'instrument-run', 'image', 'run'] - - def uses_bundles(self): - return True - - -class BasePetClinicBenchmarkSuite(BaseSpringBenchmarkSuite): - def version(self): - return "3.0.1" - - def applicationDist(self): - return mx.library("PETCLINIC_" + self.version(), True).get_path(True) - - -class PetClinicWrkBenchmarkSuite(BasePetClinicBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - """PetClinic benchmark suite that measures throughput using Wrk.""" - - def name(self): - return "petclinic-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["mixed-tiny", "mixed-small", "mixed-medium", "mixed-large", "mixed-huge"] - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(PetClinicWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - -mx_benchmark.add_bm_suite(PetClinicWrkBenchmarkSuite()) - - -class BaseSpringHelloWorldBenchmarkSuite(BaseSpringBenchmarkSuite): - def version(self): - return "3.0.6" - - def applicationDist(self): - return mx.library("SPRING_HW_" + self.version(), True).get_path(True) - - -class SpringHelloWorldWrkBenchmarkSuite(BaseSpringHelloWorldBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - def name(self): - return "spring-helloworld-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["helloworld"] - - def serviceEndpoint(self): - return 'hello' - - def defaultWorkloadPath(self, benchmark): - return os.path.join(self.applicationDist(), "workloads", benchmark + ".wrk") - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(SpringHelloWorldWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - - def getScriptPath(self, config): - return os.path.join(self.applicationDist(), "workloads", config["script"]) - - -mx_benchmark.add_bm_suite(SpringHelloWorldWrkBenchmarkSuite()) - - -class BaseQuarkusBenchmarkSuite(BaseMicroserviceBenchmarkSuite): - def get_application_startup_regex(self): - # Example of Quarkus startup log: - # "2021-03-17 20:03:33,893 INFO [io.quarkus] (main) tika-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 1.12.1.Final) started in 1.210s. Listening on: " - return r"started in (?P\d*[.,]?\d*)s." - - def get_application_startup_units(self): - return 's' - - def get_image_env(self): - # Disable experimental option checking. - return {**os.environ, "NATIVE_IMAGE_EXPERIMENTAL_OPTIONS_ARE_FATAL": "false"} - - def default_stages(self): - return ['instrument-image', 'instrument-run', 'image', 'run'] - - -class BaseQuarkusBundleBenchmarkSuite(BaseQuarkusBenchmarkSuite, NativeImageBundleBasedBenchmarkMixin): - def uses_bundles(self): - return True - - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - return self.create_bundle_command_line_args(benchmarks, bmSuiteArgs) - - -class BaseTikaBenchmarkSuite(BaseQuarkusBundleBenchmarkSuite): - def version(self): - return "1.0.11" - - def applicationDist(self): - return mx.library("TIKA_" + self.version(), True).get_path(True) - - def applicationPath(self): - return os.path.join(self.applicationDist(), "tika-quickstart-" + self.version() + "-runner.jar") - - def serviceEndpoint(self): - return 'parse' - - def extra_image_build_argument(self, benchmark, args): - # Older JDK versions would need -H:NativeLinkerOption=libharfbuzz as an extra build argument. - expectedJdkVersion = mx.VersionSpec("11.0.13") - if mx.get_jdk().version < expectedJdkVersion: - mx.abort(benchmark + " needs at least JDK version " + str(expectedJdkVersion)) - return [ - # Workaround for wrong class initialization configuration in Quarkus Tika - '--initialize-at-build-time=org.apache.pdfbox.rendering.ImageType,org.apache.pdfbox.rendering.ImageType$1,org.apache.pdfbox.rendering.ImageType$2,org.apache.pdfbox.rendering.ImageType$3,org.apache.pdfbox.rendering.ImageType$4,org.apache.xmlbeans.XmlObject,org.apache.xmlbeans.metadata.system.sXMLCONFIG.TypeSystemHolder,org.apache.xmlbeans.metadata.system.sXMLLANG.TypeSystemHolder,org.apache.xmlbeans.metadata.system.sXMLSCHEMA.TypeSystemHolder', - ] + super(BaseTikaBenchmarkSuite, self).extra_image_build_argument(benchmark, args) - - -class TikaWrkBenchmarkSuite(BaseTikaBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - """Tika benchmark suite that measures throughput using Wrk.""" - - def name(self): - return "tika-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["odt-tiny", "odt-small", "odt-medium", "odt-large", "odt-huge", "pdf-tiny", "pdf-small", "pdf-medium", "pdf-large", "pdf-huge"] - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(TikaWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - -mx_benchmark.add_bm_suite(TikaWrkBenchmarkSuite()) - - -class BaseQuarkusHelloWorldBenchmarkSuite(BaseQuarkusBundleBenchmarkSuite): - def version(self): - return "1.0.6" - - def applicationDist(self): - return mx.library("QUARKUS_HW_" + self.version(), True).get_path(True) - - def applicationPath(self): - return os.path.join(self.applicationDist(), "quarkus-hello-world-" + self.version() + "-runner.jar") - - def serviceEndpoint(self): - return 'hello' - - -class QuarkusHelloWorldWrkBenchmarkSuite(BaseQuarkusHelloWorldBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - """Quarkus benchmark suite that measures latency using Wrk2.""" - - def name(self): - return "quarkus-helloworld-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["helloworld"] - - def defaultWorkloadPath(self, benchmark): - return os.path.join(self.applicationDist(), "workloads", benchmark + ".wrk") - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(QuarkusHelloWorldWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - - def getScriptPath(self, config): - return os.path.join(self.applicationDist(), "workloads", config["script"]) - - -mx_benchmark.add_bm_suite(QuarkusHelloWorldWrkBenchmarkSuite()) - - -class BaseMicronautBenchmarkSuite(BaseMicroserviceBenchmarkSuite): - def get_application_startup_regex(self): - # Example of Micronaut startup log (there can be some formatting in between): - # "[main] INFO io.micronaut.runtime.Micronaut - Startup completed in 328ms. Server Running: " - return r"^.*\[main\].*INFO.*io.micronaut.runtime.Micronaut.*- Startup completed in (?P\d+)ms." - - def get_application_startup_units(self): - return 'ms' - - def get_image_env(self): - # Disable experimental option checking. - return {**os.environ, "NATIVE_IMAGE_EXPERIMENTAL_OPTIONS_ARE_FATAL": "false"} - - def build_assertions(self, benchmark, is_gate): - # This method overrides NativeImageMixin.build_assertions - return [] # We are skipping build assertions due to some failed asserts while building Micronaut apps. - - def default_stages(self): - return ['instrument-image', 'instrument-run', 'image', 'run'] - - -class BaseMicronautBundleBenchmarkSuite(BaseMicronautBenchmarkSuite, NativeImageBundleBasedBenchmarkMixin): - def uses_bundles(self): - return True - - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - return self.create_bundle_command_line_args(benchmarks, bmSuiteArgs) - - -class BaseQuarkusRegistryBenchmark(BaseQuarkusBenchmarkSuite, mx_sdk_benchmark.BaseMicroserviceBenchmarkSuite): - """ - This benchmark is used to measure the precision and performance of the static analysis in Native Image, - so there is no runtime load, that's why the default stage is just image. - """ - - def version(self): - return "0.0.2" - - def name(self): - return "quarkus" - - def benchmarkList(self, bmSuiteArgs): - return ["registry"] - - def default_stages(self): - return ['image'] - - def run(self, benchmarks, bmSuiteArgs): - return self.intercept_run(super(), benchmarks, bmSuiteArgs) - - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - if benchmarks is None: - mx.abort("Suite can only run a single benchmark per VM instance.") - elif len(benchmarks) != 1: - mx.abort("Must specify exactly one benchmark.") - else: - benchmark = benchmarks[0] - return self.vmArgs(bmSuiteArgs) + ["-jar", os.path.join(self.applicationDist(), benchmark + ".jar")] - - def applicationDist(self): - return mx.library("QUARKUS_REGISTRY_" + self.version(), True).get_path(True) - - def extra_image_build_argument(self, benchmark, args): - return ['-J-Dlogging.initial-configurator.min-level=500', - '-J-Dio.quarkus.caffeine.graalvm.recordStats=true', - '-J-Djava.util.logging.manager=org.jboss.logmanager.LogManager', - '-J-Dsun.nio.ch.maxUpdateArraySize=100', - '-J-DCoordinatorEnvironmentBean.transactionStatusManagerEnable=false', - '-J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory', - '-J-Dvertx.disableDnsResolver=true', - '-J-Dio.netty.leakDetection.level=DISABLED', - '-J-Dio.netty.allocator.maxOrder=3', - '-J-Duser.language=en', - '-J-Duser.country=GB', - '-J-Dfile.encoding=UTF-8', - '--features=io.quarkus.jdbc.postgresql.runtime.graal.SQLXMLFeature,org.hibernate.graalvm.internal.GraalVMStaticFeature,io.quarkus.hibernate.validator.runtime.DisableLoggingFeature,io.quarkus.hibernate.orm.runtime.graal.DisableLoggingFeature,io.quarkus.runner.Feature,io.quarkus.runtime.graal.DisableLoggingFeature,io.quarkus.caffeine.runtime.graal.CacheConstructorsFeature', - '-J--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED', - '-J--add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED', - '-J--add-opens=java.base/java.text=ALL-UNNAMED', - '-J--add-opens=java.base/java.io=ALL-UNNAMED', - '-J--add-opens=java.base/java.lang.invoke=ALL-UNNAMED', - '-J--add-opens=java.base/java.util=ALL-UNNAMED', - '-H:+AllowFoldMethods', - '-J-Djava.awt.headless=true', - '--no-fallback', - '--link-at-build-time', - '-H:+ReportExceptionStackTraces', - '-H:-AddAllCharsets', - '--enable-url-protocols=http,https', - '-H:-UseServiceLoaderFeature', - '--exclude-config', - 'io\.netty\.netty-codec', - '/META-INF/native-image/io\.netty/netty-codec/generated/handlers/reflect-config\.json', - '--exclude-config', - 'io\.netty\.netty-handler', - '/META-INF/native-image/io\.netty/netty-handler/generated/handlers/reflect-config\.json', - ] + super(BaseQuarkusBenchmarkSuite,self).extra_image_build_argument(benchmark, args) - -mx_benchmark.add_bm_suite(BaseQuarkusRegistryBenchmark()) - -_mushopConfig = { - 'order': ['--initialize-at-build-time=io.netty.handler.codec.http.cookie.ServerCookieEncoder,java.sql.DriverInfo,kotlin.coroutines.intrinsics.CoroutineSingletons'], - 'user': ['--initialize-at-build-time=io.netty.handler.codec.http.cookie.ServerCookieEncoder,java.sql.DriverInfo'], - 'payment': ['--initialize-at-build-time=io.netty.handler.codec.http.cookie.ServerCookieEncoder'] -} - -class BaseMicronautMuShopBenchmark(BaseMicronautBenchmarkSuite, mx_sdk_benchmark.BaseMicroserviceBenchmarkSuite): - """ - This benchmark suite is used to measure the precision and performance of the static analysis in Native Image, - so there is no runtime load, that's why the default stage is just image. - """ - - def version(self): - return "0.0.2" - - def name(self): - return "mushop" - - def benchmarkList(self, bmSuiteArgs): - return ["user", "order", "payment"] - - def default_stages(self): - return ['image'] - - def run(self, benchmarks, bmSuiteArgs): - return self.intercept_run(super(), benchmarks, bmSuiteArgs) - - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - if benchmarks is None: - mx.abort("Suite can only run a single benchmark per VM instance.") - elif len(benchmarks) != 1: - mx.abort("Must specify exactly one benchmark.") - else: - benchmark = benchmarks[0] - return self.vmArgs(bmSuiteArgs) + ["-jar", os.path.join(self.applicationDist(), benchmark + ".jar")] - - def applicationDist(self): - return mx.library("MICRONAUT_MUSHOP_" + self.version(), True).get_path(True) - - def extra_image_build_argument(self, benchmark, args): - return ([ - '--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk=ALL-UNNAMED', - '--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.configure=ALL-UNNAMED', - '--add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED'] - + _mushopConfig[benchmark] + super(BaseMicronautBenchmarkSuite,self).extra_image_build_argument(benchmark, args)) - -mx_benchmark.add_bm_suite(BaseMicronautMuShopBenchmark()) - - -class BaseShopCartBenchmarkSuite(BaseMicronautBundleBenchmarkSuite): - def version(self): - return "0.3.10" - - def applicationDist(self): - return mx.library("SHOPCART_" + self.version(), True).get_path(True) - - def applicationPath(self): - return os.path.join(self.applicationDist(), "shopcart-" + self.version() + ".jar") - - def serviceEndpoint(self): - return 'clients' - - -class ShopCartWrkBenchmarkSuite(BaseShopCartBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - """ShopCart benchmark suite that measures throughput using Wrk.""" - - def name(self): - return "shopcart-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["mixed-tiny", "mixed-small", "mixed-medium", "mixed-large", "mixed-huge"] - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(ShopCartWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - -mx_benchmark.add_bm_suite(ShopCartWrkBenchmarkSuite()) - - -class BaseMicronautHelloWorldBenchmarkSuite(BaseMicronautBundleBenchmarkSuite): - def version(self): - return "1.0.7" - - def applicationDist(self): - return mx.library("MICRONAUT_HW_" + self.version(), True).get_path(True) - - def applicationPath(self): - return os.path.join(self.applicationDist(), "micronaut-hello-world-" + self.version() + ".jar") - - def serviceEndpoint(self): - return 'hello' - - -class MicronautHelloWorldWrkBenchmarkSuite(BaseMicronautHelloWorldBenchmarkSuite, mx_sdk_benchmark.BaseWrkBenchmarkSuite): - def name(self): - return "micronaut-helloworld-wrk" - - def benchmarkList(self, bmSuiteArgs): - return ["helloworld"] - - def defaultWorkloadPath(self, benchmark): - return os.path.join(self.applicationDist(), "workloads", benchmark + ".wrk") - - def rules(self, out, benchmarks, bmSuiteArgs): - return self.applicationStartupRule(self.benchSuiteName(), benchmarks[0]) + super(MicronautHelloWorldWrkBenchmarkSuite, self).rules(out, benchmarks, bmSuiteArgs) - - def getScriptPath(self, config): - return os.path.join(self.applicationDist(), "workloads", config["script"]) - - -mx_benchmark.add_bm_suite(MicronautHelloWorldWrkBenchmarkSuite()) - - -class BaseDaCapoBenchmarkSuite(mx_benchmark.JavaBenchmarkSuite, mx_benchmark.AveragingBenchmarkMixin, mx_benchmark.TemporaryWorkdirMixin): - """Base benchmark suite for DaCapo-based benchmarks. - - This suite can only run a single benchmark in one VM invocation. - """ - def group(self): - return "Graal" - - def subgroup(self): - return "graal-compiler" - - def name(self): - raise NotImplementedError() - - def daCapoClasspathEnvVarName(self): - raise NotImplementedError() - - def daCapoLibraryName(self): - raise NotImplementedError() - - def daCapoPath(self): - dacapo = mx.get_env(self.daCapoClasspathEnvVarName()) - if dacapo: - return dacapo - lib = mx.library(self.daCapoLibraryName(), False) - if lib: - return lib.get_path(True) - return None - - def daCapoIterations(self): - raise NotImplementedError() - - def daCapoSizes(self): - raise NotImplementedError() - - def completeBenchmarkList(self, bmSuiteArgs): - return sorted([bench for bench in self.daCapoIterations().keys() if self.workloadSize() in self.daCapoSizes().get(bench, [])]) - - def existingSizes(self): - return list(dict.fromkeys([s for bench, sizes in self.daCapoSizes().items() for s in sizes])) - - def workloadSize(self): - raise NotImplementedError() - - def validateEnvironment(self): - if not self.daCapoPath(): - raise RuntimeError( - "Neither " + self.daCapoClasspathEnvVarName() + " variable nor " + - self.daCapoLibraryName() + " library specified.") - - def validateReturnCode(self, retcode): - return retcode == 0 - - def postprocessRunArgs(self, benchname, runArgs): - parser = argparse.ArgumentParser(add_help=False) - parser.add_argument("-n", "--iterations", default=None) - parser.add_argument("-sf", default=1, type=float, help="The total number of iterations is equivalent to the value selected by the '-n' flag scaled by this factor.") - parser.add_argument("-s", "--size", default=None) - args, remaining = parser.parse_known_args(runArgs) - - if args.size: - if args.size not in self.existingSizes(): - mx.abort("Unknown workload size '{}'. " - "Existing benchmark sizes are: {}".format(args.size, ','.join(self.existingSizes()))) - - if args.size != self.workloadSize(): - mx.abort("Mismatch between suite-defined workload size ('{}') " - "and user-provided one ('{}')!".format(self.workloadSize(), args.size)) - - otherArgs = ["-s", self.workloadSize()] + remaining - - if args.iterations: - if args.iterations.isdigit(): - return ["-n", str(int(args.sf * int(args.iterations)))] + otherArgs - if args.iterations == "-1": - return None - else: - iterations = self.daCapoIterations()[benchname] - if iterations == -1: - return None - else: - iterations = iterations + int(self.getExtraIterationCount(iterations) * args.sf) - return ["-n", str(iterations)] + otherArgs - - def createCommandLineArgs(self, benchmarks, bmSuiteArgs): - if benchmarks is None: - raise RuntimeError( - "Suite runs only a single benchmark.") - if len(benchmarks) != 1: - raise RuntimeError( - "Suite runs only a single benchmark, got: {0}".format(benchmarks)) - runArgs = self.postprocessRunArgs(benchmarks[0], self.runArgs(bmSuiteArgs)) - if runArgs is None: - return None - return ( - self.vmArgs(bmSuiteArgs) + ["-jar"] + [self.daCapoPath()] + - [benchmarks[0]] + runArgs) - - def benchmarkList(self, bmSuiteArgs): - missing_sizes = set(self.daCapoIterations().keys()).difference(set(self.daCapoSizes().keys())) - if len(missing_sizes) > 0: - mx.abort("Missing size definitions for benchmark(s): {}".format(missing_sizes)) - return [b for b, it in self.daCapoIterations().items() - if self.workloadSize() in self.daCapoSizes().get(b, []) and it != -1] - - def successPatterns(self): - return [ - # Due to the non-determinism of DaCapo version printing, we only match the name. - re.compile( - r"^===== DaCapo (?P[^\n]+) ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====", # pylint: disable=line-too-long - re.MULTILINE) - ] - - def failurePatterns(self): - return [ - # Due to the non-determinism of DaCapo version printing, we only match the name. - re.compile( - r"^===== DaCapo (?P[^\n]+) ([a-zA-Z0-9_]+) FAILED (warmup|) =====", # pylint: disable=line-too-long - re.MULTILINE), - re.compile( - r"^\[\[\[Graal compilation failure\]\]\]", # pylint: disable=line-too-long - re.MULTILINE) - ] - - def shorten_vm_flags(self, args): - return mx_benchmark.Rule.crop_back("...")(' '.join(args)) - - def rules(self, out, benchmarks, bmSuiteArgs): - runArgs = self.postprocessRunArgs(benchmarks[0], self.runArgs(bmSuiteArgs)) - if runArgs is None: - return [] - totalIterations = int(runArgs[runArgs.index("-n") + 1]) - return [ - # Due to the non-determinism of DaCapo version printing, we only match the name. - mx_benchmark.StdOutRule( - r"===== DaCapo (?P[^\n]+) (?P[a-zA-Z0-9_]+) PASSED in (?P