Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import org.apache.lucene.gradle.plugins.LuceneGradlePlugin;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
Expand Down Expand Up @@ -189,7 +190,7 @@ public void apply(Project project) {
task.jvmArgs(
List.of(
"-XX:StartFlightRecording=dumponexit=true,maxsize=250M,settings="
+ gradlePluginResource(project, "testing/profiling.jfc"),
+ gradlePluginResource(project, profilingSettingsPath()),
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+DebugNonSafepoints"));
task.dependsOn(cleanPreviousProfiles);
Expand Down Expand Up @@ -254,4 +255,14 @@ private record ProfilingOptions(
Provider<Integer> countOption,
Provider<Boolean> lineNumbersOption,
Provider<Boolean> frametypesOption) {}

/**
* JEP 509 CPU-time sampling ({@code jdk.CPUTimeSample}) is implemented on Linux. Use a Linux-only
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe is currently (Java 25) implemented only on Linux, so we use a Linux-only JFR template...?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, updated. Thanks!

* JFR template with CPU-time sampling only; other hosts keep wall-clock execution sampling for
* short tests.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, it's for all tests, not just short tests right? Maybe just remove for short tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done. Updated. Thanks!

*/
private static String profilingSettingsPath() {
String os = System.getProperty("os.name", "").toLowerCase(Locale.ROOT);
return os.contains("linux") ? "testing/profiling.linux.jfc" : "testing/profiling.jfc";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, instead of baking linux in the name, could we use cputime? Maybe in the future other OS's can support CPU time sampling too...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, makes sense. Thanks!

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,16 @@ static boolean isInteresting(String mode, RecordedEvent event) {
String name = event.getEventType().getName();
switch (mode) {
case "cpu":
return (name.equals("jdk.ExecutionSample") || name.equals("jdk.NativeMethodSample"))
&& !isGradlePollThread(event.getThread("sampledThread"));
// jdk.CPUTimeSample: JEP 509 (e.g. gradle/testing/profiling.linux.jfc). Legacy samples:
// jdk.ExecutionSample / jdk.NativeMethodSample (e.g. profiling.jfc). Stock Lucene configs
// enable one family; filter gradle poll thread for legacy samples only.
if (name.equals("jdk.CPUTimeSample")) {
return true;
}
if (name.equals("jdk.ExecutionSample") || name.equals("jdk.NativeMethodSample")) {
return !isGradlePollThread(event.getThread("sampledThread"));
}
return false;
case "heap":
return (name.equals("jdk.ObjectAllocationInNewTLAB")
|| name.equals("jdk.ObjectAllocationOutsideTLAB"))
Expand All @@ -132,6 +140,8 @@ static long getValue(RecordedEvent event) {
return 1L;
case "jdk.NativeMethodSample":
return 1L;
case "jdk.CPUTimeSample":
return 1L;
default:
throw new UnsupportedOperationException(event.toString());
}
Expand Down Expand Up @@ -173,6 +183,7 @@ public static void printReport(
if (count < 1) {
throw new IllegalArgumentException("tests.profile.count must be positive");
}

Map<String, SimpleEntry<String, Long>> histogram = new HashMap<>();
int totalEvents = 0;
long sumValues = 0;
Expand Down
4 changes: 3 additions & 1 deletion gradle/testing/profiling.jfc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
limitations under the License.
-->
<!--
Collects only execution and method samples at a low interval
Wall-clock execution samples for CPU profiling on platforms where JEP 509 CPU-time sampling
is unavailable (non-Linux). On Linux, CodeProfilingPlugin uses profiling.linux.jfc instead.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a profiling.linux.jfc in your PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad, missed it in adding in previous commit. Thanks!

Heap allocation events are enabled on all platforms.
-->
<configuration version="2.0" label="TestProfiling" description="Sampling for unit tests" provider="Apache">
<event name="jdk.ExecutionSample">
Expand Down
46 changes: 46 additions & 0 deletions gradle/testing/profiling.linux.jfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Linux: JEP 509 jdk.CPUTimeSample only (no jdk.ExecutionSample / jdk.NativeMethodSample).
Wall-clock sampling at 1 ms added measurable overhead in long runs; CPU-time sampling keeps
short tests useful via a 1 ms throttle while avoiding duplicate wall-clock + CPU samplers.
-->
<configuration version="2.0" label="TestProfilingLinux" description="CPU-time sampling for unit tests (Linux)" provider="Apache">
<event name="jdk.ExecutionSample">
<setting name="enabled">false</setting>
</event>

<event name="jdk.NativeMethodSample">
<setting name="enabled">false</setting>
</event>

<event name="jdk.CPUTimeSample">
<setting name="enabled">true</setting>
<setting name="throttle">1 ms</setting>
</event>

<event name="jdk.ObjectAllocationInNewTLAB">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ObjectAllocationOutsideTLAB">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>
</configuration>
5 changes: 5 additions & 0 deletions lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ Changes in Runtime Behavior

Build
---------------------
* GITHUB#15926: Support jdk.CPUTimeSample event (Java 25+, JEP 509) in ProfileResults.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we word a bit more user-friendly-y? Maybe Use the new (Java 25+, JEP 509) CPU time sampling profiler when available (currently just on Linux), and fall back to the legacy wall-clock...?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, done. thanks!

Linux test JVMs use gradle/testing/profiling.linux.jfc (CPU-time sampling only); other hosts
keep wall-clock jdk.ExecutionSample/jdk.NativeMethodSample. CodeProfilingPlugin selects the
JFR settings file by host OS. (Prithvi S)

* GITHUB#15327: New low-level build options to detect abuse of LuceneTestCase.random():
tests.random.maxacquires and tests.random.maxcalls (Robert Muir, Dawid Weiss)

Expand Down
Loading