Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions narayana/ArjunaCore/arjuna/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,12 @@
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
</dependency>
<!-- Source: https://mvnrepository.com/artifact/tools.profiler/async-profiler -->
<dependency>
<groupId>tools.profiler</groupId>
<artifactId>async-profiler</artifactId>
<version>4.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
Expand All @@ -20,6 +21,12 @@
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.profile.JavaFlightRecorderProfiler;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
Expand All @@ -39,8 +46,8 @@
@Warmup(iterations = VTPerformanceTest.ITERATIONS, time = VTPerformanceTest.TIME_PER_ITER, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = VTPerformanceTest.ITERATIONS, time = VTPerformanceTest.TIME_PER_ITER, timeUnit = TimeUnit.SECONDS)
public class VTPerformanceTest {
static final int THREADS = 10;//_000; //Threads.MAX;
static final int FORKS = 2;
static final int THREADS = 240;//10;//_000; //Threads.MAX;
static final int FORKS = 1;
static final int ITERATIONS = 5;
static final int TIME_PER_ITER = 2;

Expand All @@ -51,6 +58,32 @@ public class VTPerformanceTest {
private static MethodHandle shutdownExecutorMH; // method handle to shut down the executor
private static boolean isVirtualThreadPerTaskExecutor;

public static void main(String[] args) throws RunnerException {
// Sometimes it is useful to run the benchmark directly from an IDE:
Options opt = new OptionsBuilder()
.include(VTPerformanceTest.class.getSimpleName() + ".standardThreadsBenchmark")
.timeUnit(TimeUnit.SECONDS)
.threads(THREADS)
.forks(FORKS)
.mode(Mode.Throughput)
.warmupIterations(1)
.warmupTime(TimeValue.seconds(1))
.measurementIterations(ITERATIONS)
.measurementTime(TimeValue.seconds(TIME_PER_ITER))
.param("networkDelay", "0") // don't simulate network using MS_DELAY
.shouldDoGC(true)
// use JFR as the profiler, the recording will appear in the User working directory with the
// name "<package name>-xxx/profile.jfr", which you can change to "wherever" using
// addProfiler(JavaFlightRecorderProfiler.class, "dir=wherever"). Java Flight Recorder data files
// can be viewed with the jmc graphical tool or with the jfr command line tool which is in the java
// bin directory
.addProfiler(JavaFlightRecorderProfiler.class)
.jvmArgs("-Djmh.executor=FJP") // ForkJoinPool
.build();

new Runner(opt).run();
}

@State(Scope.Benchmark)
public static class VTBenchmarkState {
@Param({"0", MS_DELAY}) // run the benchmark twice with and without simulating a network delay
Expand Down Expand Up @@ -129,6 +162,11 @@ private void twoPhase(int msDelay) {
public static void beforeClass(String msg, boolean async, boolean enableVT) {
CoordinatorEnvironmentBean configBean = arjPropertyManager.getCoordinatorEnvironmentBean();

// size the standard TwoPhaseCommit thread pool to match the number of threads used for the benchmark,
// this provides a fairer comparison between the standard fork-join pool and the virtual threads executor,
// refer to the various TwoPhaseCommitThreadPool implementations for details
configBean.setMaxTwoPhaseCommitThreads(THREADS);

configBean.setAsyncPrepare(async);
configBean.setAsyncCommit(async);
configBean.setAsyncRollback(async);
Expand Down
8 changes: 8 additions & 0 deletions narayana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ Here we have overridden the defaults and specified "-i 1 -wi 2 -f 1 -t 2 -r 10"

We also passed in a wild card (.\*) to say run all benchmark methods contained in the class VolatileStoreBenchmark.

To run the benchmark with a profiler pass the appropriate profiler options via the java command line. For example to the run the VTPerformanceTest using the JFR profiler use the following options:

java -XX:+FlightRecorder -XX:StartFlightRecording=duration=200s,filename=flight.jfr -jar ArjunaCore/arjuna/target/benchmarks.jar com.hp.mwtests.ts.arjuna.performance.VTPerformanceTest

Some benchmarks, such as the one just referenced, also have a main method to simplify profiling and running from an IDE.

Profiler data can be viewed with tools specific to the profiler, for example JFR data can be viewed with the jmc graphical tool or with the jfr command line tool located in the java bin directory.

And finally, to debug a benchmark use the surefire debug property, for example `mvn clean test -Dtest=TestBenchmark#testImprovement -Dmaven.surefire.debug`

It is straightforward to write your own benchmark code, just tell the framework which methods are benchmarks by annotating them with @Benchmark. There are plenty of examples in this git repository.
Expand Down