This is an automated email from the ASF dual-hosted git repository. clebertsuconic pushed a commit to branch branch-jni in repository https://gitbox.apache.org/repos/asf/artemis-native.git
commit 43403880a7df61d7d12666aa4f18a1cb0cebbff7 Author: mayankkunwar <[email protected]> AuthorDate: Fri Apr 24 17:07:38 2026 +0100 Adding JMH performance test --- pom.xml | 27 ++++ .../test/performance/jmh/BenchmarkRunner.java | 11 ++ .../test/performance/jmh/LibaioBenchmark.java | 165 +++++++++++++++++++++ 3 files changed, 203 insertions(+) diff --git a/pom.xml b/pom.xml index d4693f8..107367f 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,7 @@ <version.org.jacoco.plugin>0.8.6</version.org.jacoco.plugin> <surefire.version>2.22.2</surefire.version> <junit.version>4.13.2</junit.version> + <jmh.version>1.37</jmh.version> <maven.bundle.plugin.version>5.1.2</maven.bundle.plugin.version> <exec-maven-plugin.version>3.0.0</exec-maven-plugin.version> <maven-enforcer-plugin.version>3.0.0</maven-enforcer-plugin.version> @@ -98,6 +99,18 @@ <scope>test</scope> <!-- License: EPL 1.0 --> </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-core</artifactId> + <version>${jmh.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <version>${jmh.version}</version> + <scope>test</scope> + </dependency> <dependency> <groupId>org.jacoco</groupId> <artifactId>org.jacoco.ant</artifactId> @@ -261,6 +274,20 @@ <build> <pluginManagement> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.11.0</version> + <configuration> + <annotationProcessorPaths> + <path> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <version>${jmh.version}</version> + </path> + </annotationProcessorPaths> + </configuration> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> diff --git a/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/BenchmarkRunner.java b/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/BenchmarkRunner.java new file mode 100644 index 0000000..ca57d78 --- /dev/null +++ b/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/BenchmarkRunner.java @@ -0,0 +1,11 @@ +package org.apache.activemq.artemis.nativo.jlibaio.test.performance.jmh; + +import org.openjdk.jmh.Main; + +import java.io.IOException; + +public class BenchmarkRunner { + public static void main(String[] args) throws IOException { + Main.main(args); + } +} diff --git a/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/LibaioBenchmark.java b/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/LibaioBenchmark.java new file mode 100644 index 0000000..44310df --- /dev/null +++ b/src/test/java/org/apache/activemq/artemis/nativo/jlibaio/test/performance/jmh/LibaioBenchmark.java @@ -0,0 +1,165 @@ +package org.apache.activemq.artemis.nativo.jlibaio.test.performance.jmh; + +import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext; +import org.apache.activemq.artemis.nativo.jlibaio.LibaioFile; +import org.apache.activemq.artemis.nativo.jlibaio.SubmitInfo; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +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; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.io.File; +import java.nio.ByteBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 2) +@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) +public class LibaioBenchmark { + private static final int FILE_SIZE = 10000 * 4096; + private static final int BLOCK_SIZE = 4096; + + @Param({"2048"}) + private static int LIBAIO_QUEUE_SIZE; + + @Param({"10000"}) + private int recordCount; + + private File file; + private LibaioContext<SubmitInfo> control; + private LibaioFile<SubmitInfo> libaioFile; + + private ByteBuffer headerBuffer; + private ByteBuffer recordBuffer; + + private final AtomicReference<CountDownLatch> currentLatch = new AtomicReference<>(); + + private Thread pollThread; + private volatile boolean polling = true; + + private final SubmitInfo callback = new SubmitInfo() { + @Override + public void onError(int errno, String message) { + // ignore for benchmark + } + + @Override + public void done() { + CountDownLatch latch = currentLatch.get(); + if (latch != null) { + latch.countDown(); + } + } + }; + + private long fileId = 1L; + + @Setup(Level.Trial) + public void setup() throws Exception { + file = File.createTempFile("aio-bench-jni-", ".dat"); + + control = new LibaioContext<>(LIBAIO_QUEUE_SIZE, true, true); + libaioFile = control.openFile(file, true); + + libaioFile.fallocate(FILE_SIZE); + + headerBuffer = LibaioContext.newAlignedBuffer(BLOCK_SIZE, BLOCK_SIZE); + recordBuffer = LibaioContext.newAlignedBuffer(BLOCK_SIZE, BLOCK_SIZE); + + initRecord(headerBuffer); // filling the record clock with 1 + initRecord(recordBuffer); // filling the record clock with 1 + + fillHeader(fileId); + updateRecord(recordBuffer, fileId, 0L); + + polling = true; + pollThread = new Thread(() -> { + try { + while (polling && !Thread.currentThread().isInterrupted()) { + control.poll(); + } + } catch (Throwable t) { + } + }, "aio-jmh-jni-poll-thread"); + pollThread.setDaemon(true); + pollThread.start(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + polling = false; + + if (pollThread != null) { + pollThread.interrupt(); + pollThread.join(TimeUnit.SECONDS.toMillis(10)); + } + + if (libaioFile != null) { + libaioFile.close(); + } + if (control != null) { + control.close(); + } + if (headerBuffer != null) { + LibaioContext.freeBuffer(headerBuffer); + } + if (recordBuffer != null) { + LibaioContext.freeBuffer(recordBuffer); + } + if (file != null) { + file.delete(); + } + } + + @Benchmark + public void writeHeaderAndRecords() throws Exception { + CountDownLatch latch = new CountDownLatch(recordCount * 100); + currentLatch.set(latch); + + try { + fillHeader(fileId); +// libaioFile.write(0L, BLOCK_SIZE, headerBuffer, callback); + + for (int j = 0; j < 100; j++) { + for (int i = 0; i < recordCount; i++) { + updateRecord(recordBuffer, fileId, i); + long offset = BLOCK_SIZE + ((long) i * BLOCK_SIZE); + libaioFile.write(offset, BLOCK_SIZE, recordBuffer, callback); + } + } + + latch.await(); + } finally { + currentLatch.compareAndSet(latch, null); + } + } + + private void fillHeader(long fileId) { + headerBuffer.putLong(0, fileId); + } + + private void updateRecord(ByteBuffer buffer, long fileId, long recordId) { + buffer.putLong(0, fileId); + buffer.putLong(8, recordId); + } + + private void initRecord(ByteBuffer record) { + while (record.position() < BLOCK_SIZE) { + record.put((byte) 1); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
