Skip to content

Commit 85877b9

Browse files
committed
Add MemorySegment function to "Put" benchmark.
1 parent dcb5c47 commit 85877b9

2 files changed

Lines changed: 70 additions & 8 deletions

File tree

src/main/c++/getputjni/GetPutJNI.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ extern "C" int getIntoMemorySegment(const char* key, char* dest, int dest_len) {
384384
return size;
385385
}
386386

387+
extern "C" int putFromMemorySegment(const char* key, const char* src, int src_len) {
388+
char *db_buf = GetByteArrayInternalForWrite(key, src_len);
389+
memcpy(db_buf, src, src_len);
390+
return src_len;
391+
}
392+
387393
/*
388394
* Class: com_evolvedbinary_jnibench_common_getputjni_GetPutJNI
389395
* Method: putFromIndirectByteBufferGetRegion

src/main/java/com/evolvedbinary/jnibench/jmhbench/PutJNIBenchmark.java

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,26 @@
3030
import com.evolvedbinary.jnibench.consbench.NarSystem;
3131
import com.evolvedbinary.jnibench.jmhbench.cache.*;
3232
import com.evolvedbinary.jnibench.jmhbench.common.*;
33+
import io.netty.buffer.ByteBuf;
3334
import io.netty.buffer.PooledByteBufAllocator;
35+
import java.lang.foreign.Arena;
36+
import java.lang.foreign.FunctionDescriptor;
37+
import java.lang.foreign.Linker;
38+
import java.lang.foreign.MemorySegment;
39+
import java.lang.foreign.SymbolLookup;
40+
import java.lang.foreign.ValueLayout;
41+
import java.lang.invoke.MethodHandle;
42+
import java.nio.ByteBuffer;
43+
import java.text.SimpleDateFormat;
44+
import java.util.Date;
45+
import java.util.concurrent.TimeUnit;
46+
import java.util.logging.Logger;
3447
import org.openjdk.jmh.annotations.*;
3548
import org.openjdk.jmh.infra.Blackhole;
3649
import org.openjdk.jmh.runner.Runner;
3750
import org.openjdk.jmh.runner.RunnerException;
3851
import org.openjdk.jmh.runner.options.Options;
3952
import org.openjdk.jmh.runner.options.OptionsBuilder;
40-
import io.netty.buffer.ByteBuf;
41-
42-
import java.nio.ByteBuffer;
43-
import java.text.SimpleDateFormat;
44-
import java.util.Date;
45-
import java.util.concurrent.TimeUnit;
46-
import java.util.logging.Logger;
4753

4854
/**
4955
* Benchmark getting byte arrays from native methods.
@@ -58,8 +64,24 @@ public class PutJNIBenchmark {
5864

5965
private static final Logger LOG = Logger.getLogger(GetJNIBenchmark.class.getName());
6066

67+
private static final MethodHandle PUT_FROM_MEMORY_SEGMENT_HANDLE;
68+
6169
static {
6270
NarSystem.loadLibrary();
71+
72+
// 2. Initialize the Linker and Lookup
73+
Linker linker = Linker.nativeLinker();
74+
SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
75+
76+
// 3. Find the symbol and create the Downcall Handle once
77+
PUT_FROM_MEMORY_SEGMENT_HANDLE = loaderLookup.find("putFromMemorySegment")
78+
.map(symbol -> linker.downcallHandle(symbol,
79+
FunctionDescriptor.of(
80+
ValueLayout.JAVA_INT,
81+
ValueLayout.ADDRESS,
82+
ValueLayout.ADDRESS,
83+
ValueLayout.JAVA_INT)))
84+
.orElseThrow();
6385
}
6486

6587
@State(Scope.Benchmark)
@@ -90,6 +112,8 @@ public static class GetJNIBenchmarkState {
90112

91113
String keyBase;
92114
byte[] keyBytes;
115+
MemorySegment keyMemorySegment;
116+
private Arena benchmarkArena;
93117

94118
JMHCaller caller;
95119

@@ -99,14 +123,19 @@ public void setup() {
99123

100124
keyBase = "testKeyWithReturnValueSize" + String.format("%07d", valueSize) + "Bytes";
101125

126+
benchmarkArena = Arena.ofShared();
127+
102128
keyBytes = keyBase.getBytes();
129+
keyMemorySegment = benchmarkArena.allocateArray(ValueLayout.JAVA_BYTE, keyBytes);
103130

104131
writePreparation = AllocationCache.Prepare.valueOf(preparation);
105132
}
106133

107134
@TearDown
108135
public void tearDown() {
109-
136+
if (benchmarkArena != null) {
137+
benchmarkArena.close();
138+
}
110139
}
111140
}
112141

@@ -117,6 +146,7 @@ public static class GetJNIThreadState {
117146
private final UnsafeBufferCache unsafeBufferCache = new UnsafeBufferCache();
118147
private final ByteArrayCache byteArrayCache = new ByteArrayCache();
119148
private final IndirectByteBufferCache indirectByteBufferCache = new IndirectByteBufferCache();
149+
private final MemorySegmentCache memorySegmentCache = new MemorySegmentCache();
120150
private final PooledByteBufAllocator pooledByteBufAllocator = PooledByteBufAllocator.DEFAULT;
121151
private final NettyByteBufCache nettyByteBufCache = new NettyByteBufCache();
122152

@@ -152,6 +182,9 @@ public void setup(GetJNIBenchmarkState benchmarkState, Blackhole blackhole) {
152182
case "putFromByteArrayCritical":
153183
byteArrayCache.setup(valueSize, cacheSize, benchmarkState.cacheEntryOverhead, benchmarkState.writePreparation, blackhole);
154184
break;
185+
case "putFromMemorySegment":
186+
memorySegmentCache.setup(valueSize, cacheSize, benchmarkState.cacheEntryOverhead, benchmarkState.writePreparation, blackhole);
187+
break;
155188
default:
156189
throw new RuntimeException("Don't know how to setup() for benchmark: " + benchmarkState.caller.benchmarkMethod);
157190
}
@@ -184,6 +217,9 @@ public void tearDown(GetJNIBenchmarkState benchmarkState) {
184217
case "putFromByteArrayCritical":
185218
byteArrayCache.tearDown();
186219
break;
220+
case "putFromMemorySegment":
221+
memorySegmentCache.tearDown();
222+
break;
187223
default:
188224
throw new RuntimeException("Don't know how to tearDown() for benchmark: " + benchmarkState.caller.benchmarkMethod);
189225
}
@@ -196,6 +232,26 @@ public void buffersOnlyDirectByteBufferFromUnsafe(GetJNIThreadState threadState)
196232
threadState.unsafeBufferCache.release(unsafeBuffer);
197233
}
198234

235+
@Benchmark
236+
public void putFromMemorySegment(GetJNIBenchmarkState benchmarkState, GetJNIThreadState threadState,
237+
Blackhole blackhole) {
238+
final var segment = threadState.memorySegmentCache.acquire();
239+
threadState.memorySegmentCache.prepareBuffer(segment, benchmarkState.fillByte);
240+
241+
try {
242+
final var size = (int) PUT_FROM_MEMORY_SEGMENT_HANDLE.invokeExact(
243+
benchmarkState.keyMemorySegment, // Pre-allocated segment for key
244+
segment,
245+
benchmarkState.valueSize
246+
);
247+
blackhole.consume(size);
248+
} catch (Throwable e) {
249+
throw new RuntimeException(e);
250+
}
251+
252+
threadState.memorySegmentCache.release(segment);
253+
}
254+
199255
@Benchmark
200256
public void putFromDirectByteBuffer(GetJNIBenchmarkState benchmarkState, GetJNIThreadState threadState, Blackhole blackhole) {
201257
ByteBuffer byteBuffer = threadState.directByteBufferCache.acquire();

0 commit comments

Comments
 (0)