diff --git a/jmh-fork/jmh-core/native-instrument-hooks/src/main/c/instrument_hooks_jni.c b/jmh-fork/jmh-core/native-instrument-hooks/src/main/c/instrument_hooks_jni.c
index ffb5015..11a6499 100644
--- a/jmh-fork/jmh-core/native-instrument-hooks/src/main/c/instrument_hooks_jni.c
+++ b/jmh-fork/jmh-core/native-instrument-hooks/src/main/c/instrument_hooks_jni.c
@@ -16,7 +16,7 @@ static void throw_runtime_exception(JNIEnv *env, const char *msg) {
// --- Static methods ---
JNIEXPORT jlong JNICALL
-Java_io_codspeed_instrument_1hooks_InstrumentHooks_currentTimestamp(
+Java_io_codspeed_instrument_1hooks_InstrumentHooks_nativeCurrentTimestamp(
JNIEnv *env, jclass cls) {
(void)env;
(void)cls;
diff --git a/jmh-fork/jmh-core/pom.xml b/jmh-fork/jmh-core/pom.xml
index 847f927..96f3f90 100644
--- a/jmh-fork/jmh-core/pom.xml
+++ b/jmh-fork/jmh-core/pom.xml
@@ -119,6 +119,7 @@ questions.
src/main/java/io/codspeed/**
src/test/java/io/codspeed/**
+ native-*/**
diff --git a/jmh-fork/jmh-core/src/main/java/io/codspeed/instrument_hooks/InstrumentHooks.java b/jmh-fork/jmh-core/src/main/java/io/codspeed/instrument_hooks/InstrumentHooks.java
index 26ce843..50ef867 100644
--- a/jmh-fork/jmh-core/src/main/java/io/codspeed/instrument_hooks/InstrumentHooks.java
+++ b/jmh-fork/jmh-core/src/main/java/io/codspeed/instrument_hooks/InstrumentHooks.java
@@ -63,7 +63,11 @@ public static InstrumentHooks getInstance() {
public static final int FEATURE_DISABLE_CALLGRIND_MARKERS = 0;
// Static methods (no instance needed)
- public static native long currentTimestamp();
+ public static long currentTimestamp() {
+ return nativeAvailable ? nativeCurrentTimestamp() : 0L;
+ }
+
+ private static native long nativeCurrentTimestamp();
public static native void setFeature(int feature, boolean enabled);
diff --git a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java
index 03adf5b..c1092a8 100644
--- a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java
+++ b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java
@@ -50,6 +50,17 @@
*/
abstract class BaseRunner {
+ /**
+ * System property the parent Runner sets on forked JVMs whose iterations are warmup-only
+ * (results discarded). The forked process reads it to suppress CodSpeed marker emission so the
+ * runner only sees real measurement regions.
+ */
+ static final String CODSPEED_WARMUP_FORK_PROP = "io.codspeed.warmupFork";
+
+ static boolean isWarmupFork() {
+ return "true".equals(System.getProperty(CODSPEED_WARMUP_FORK_PROP));
+ }
+
private long projectedTotalTime;
private long projectedRunningTime;
private long actualRunningTime;
@@ -291,7 +302,17 @@ protected void runBenchmark(BenchmarkParams benchParams, BenchmarkHandler handle
boolean isFirstIteration = (benchParams.getWarmup().getCount() == 0) && (i == 1);
boolean isLastIteration = (i == mp.getCount());
+
+ long startTs = InstrumentHooks.currentTimestamp();
IterationResult ir = handler.runIteration(benchParams, mp, isFirstIteration, isLastIteration);
+ long endTs = InstrumentHooks.currentTimestamp();
+
+ if (!isWarmupFork()) {
+ InstrumentHooks hooks = InstrumentHooks.getInstance();
+ int pid = (int) ProcessHandle.current().pid();
+ hooks.addMarker(pid, InstrumentHooks.MARKER_TYPE_BENCHMARK_START, startTs);
+ hooks.addMarker(pid, InstrumentHooks.MARKER_TYPE_BENCHMARK_END, endTs);
+ }
out.iterationResult(benchParams, mp, i, ir);
allMeasurement += ir.getMetadata().getAllOps();
diff --git a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java
index a4339cf..abd926f 100644
--- a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java
+++ b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java
@@ -681,7 +681,7 @@ private Multimap runSeparate(ActionPlan action
for (int i = 0; i < totalForks; i++) {
boolean warmupFork = (i < warmupForkCount);
- List forkedString = getForkedMainCommand(params, profilers, server.getHost(), server.getPort());
+ List forkedString = getForkedMainCommand(params, profilers, server.getHost(), server.getPort(), warmupFork);
etaBeforeBenchmark();
@@ -844,11 +844,18 @@ private List doFork(BinaryLinkServer reader, List comma
}
/**
- * @param host host VM host
- * @param port host VM port
- * @return
+ * Build the command line used to launch a forked benchmark JVM.
+ *
+ * @param benchmark benchmark parameters for the current run
+ * @param profilers external profilers contributing extra JVM args
+ * @param host host VM host
+ * @param port host VM port
+ * @param warmupFork true for warmup-only forks whose results are discarded; causes
+ * {@code -D}{@value BaseRunner#CODSPEED_WARMUP_FORK_PROP}{@code =true}
+ * to be added so the forked JVM suppresses CodSpeed marker emission
+ * @return the full argv, starting with the JVM executable
*/
- List getForkedMainCommand(BenchmarkParams benchmark, List profilers, String host, int port) {
+ List getForkedMainCommand(BenchmarkParams benchmark, List profilers, String host, int port, boolean warmupFork) {
// Poll profilers for options
List javaInvokeOptions = new ArrayList<>();
List javaOptions = new ArrayList<>();
@@ -876,6 +883,10 @@ List getForkedMainCommand(BenchmarkParams benchmark, ListemptyList(),
System.getProperty("java.version"), System.getProperty("java.vm.name"), System.getProperty("java.vm.version"), Version.getPlainVersion(),
TimeValue.days(1));
- List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT);
+ List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT, false);
// expecting 1 compile command file
List files = CompilerHints.getCompileCommandFiles(command);
@@ -100,7 +100,7 @@ public void testOptsWithCompileCommandFileResultInMergedCompileCommandFile() thr
Utils.getCurrentJvm(), Collections.singletonList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints),
System.getProperty("java.version"), System.getProperty("java.vm.name"), System.getProperty("java.vm.version"), Version.getPlainVersion(),
TimeValue.days(1));
- List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT);
+ List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT, false);
// expecting 1 compile command file
List files = CompilerHints.getCompileCommandFiles(command);
@@ -137,7 +137,7 @@ public void testOptsWith2CompileCommandFilesResultInMergedCompileCommandFile() t
Arrays.asList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints1, CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints2),
System.getProperty("java.version"), System.getProperty("java.vm.name"), System.getProperty("java.vm.version"), Version.getPlainVersion(),
TimeValue.days(1));
- List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT);
+ List command = blade.getForkedMainCommand(bp, Collections.emptyList(), DUMMY_HOST, DUMMY_PORT, false);
// expecting 1 compile command file
List files = CompilerHints.getCompileCommandFiles(command);