31 import org.openjdk.jmh.annotations.Setup;
32 import org.openjdk.jmh.annotations.Param;
33 import org.openjdk.jmh.annotations.TearDown;
34 import org.openjdk.jmh.annotations.Measurement;
35 import org.openjdk.jmh.annotations.Mode;
36 import org.openjdk.jmh.annotations.OutputTimeUnit;
37 import org.openjdk.jmh.annotations.State;
38 import org.openjdk.jmh.annotations.Warmup;
39
40 import java.lang.foreign.MemorySegment.Scope;
41 import java.lang.invoke.MethodHandle;
42 import java.util.concurrent.TimeUnit;
43
44 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
45
46 @BenchmarkMode(Mode.AverageTime)
47 @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
48 @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
49 @State(org.openjdk.jmh.annotations.Scope.Thread)
50 @OutputTimeUnit(TimeUnit.NANOSECONDS)
51 @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" })
52 public class StrLenTest extends CLayouts {
53
54 Arena arena = Arena.ofConfined();
55
56 SegmentAllocator segmentAllocator;
57 SegmentAllocator arenaAllocator = new RingAllocator(arena);
58 SlicingPool pool = new SlicingPool();
59
60 @Param({"5", "20", "100"})
61 public int size;
62 public String str;
63
64 static {
65 System.loadLibrary("StrLen");
66 }
67
68 static final MethodHandle STRLEN;
69
70 static {
71 Linker abi = Linker.nativeLinker();
75
76 @Setup
77 public void setup() {
78 str = makeString(size);
79 segmentAllocator = SegmentAllocator.prefixAllocator(arena.allocate(size + 1, 1));
80 }
81
82 @TearDown
83 public void tearDown() {
84 arena.close();
85 }
86
87 @Benchmark
88 public int jni_strlen() throws Throwable {
89 return strlen(str);
90 }
91
92 @Benchmark
93 public int panama_strlen() throws Throwable {
94 try (Arena arena = Arena.ofConfined()) {
95 MemorySegment segment = arena.allocateUtf8String(str);
96 return (int)STRLEN.invokeExact(segment);
97 }
98 }
99
100 @Benchmark
101 public int panama_strlen_ring() throws Throwable {
102 return (int)STRLEN.invokeExact(arenaAllocator.allocateUtf8String(str));
103 }
104
105 @Benchmark
106 public int panama_strlen_pool() throws Throwable {
107 Arena arena = pool.acquire();
108 int l = (int) STRLEN.invokeExact(arena.allocateUtf8String(str));
109 arena.close();
110 return l;
111 }
112
113 @Benchmark
114 public int panama_strlen_prefix() throws Throwable {
115 return (int)STRLEN.invokeExact(segmentAllocator.allocateUtf8String(str));
116 }
117
118 @Benchmark
119 public int panama_strlen_unsafe() throws Throwable {
120 MemorySegment address = makeStringUnsafe(str);
121 int res = (int) STRLEN.invokeExact(address);
122 freeMemory(address);
123 return res;
124 }
125
126 static MemorySegment makeStringUnsafe(String s) {
127 byte[] bytes = s.getBytes();
128 int len = bytes.length;
129 MemorySegment address = allocateMemory(len + 1);
130 MemorySegment str = address.asSlice(0, len + 1);
131 str.copyFrom(MemorySegment.ofArray(bytes));
132 str.set(JAVA_BYTE, len, (byte)0);
133 return address;
134 }
135
145 """;
146 return lorem.substring(0, size);
147 }
148
149 static class RingAllocator implements SegmentAllocator {
150 final MemorySegment segment;
151 SegmentAllocator current;
152 long rem;
153
154 public RingAllocator(Arena session) {
155 this.segment = session.allocate(1024, 1);
156 reset();
157 }
158
159 @Override
160 public MemorySegment allocate(long byteSize, long byteAlignment) {
161 if (rem < byteSize) {
162 reset();
163 }
164 MemorySegment res = current.allocate(byteSize, byteAlignment);
165 long lastOffset = segment.segmentOffset(res) + res.byteSize();
166 rem = segment.byteSize() - lastOffset;
167 return res;
168 }
169
170 void reset() {
171 current = SegmentAllocator.slicingAllocator(segment);
172 rem = segment.byteSize();
173 }
174 }
175
176 static class SlicingPool {
177 final MemorySegment pool = Arena.ofAuto().allocate(1024);
178 boolean isAcquired = false;
179
180 public Arena acquire() {
181 if (isAcquired) {
182 throw new IllegalStateException("An allocator is already in use");
183 }
184 isAcquired = true;
185 return new SlicingPoolAllocator();
|
31 import org.openjdk.jmh.annotations.Setup;
32 import org.openjdk.jmh.annotations.Param;
33 import org.openjdk.jmh.annotations.TearDown;
34 import org.openjdk.jmh.annotations.Measurement;
35 import org.openjdk.jmh.annotations.Mode;
36 import org.openjdk.jmh.annotations.OutputTimeUnit;
37 import org.openjdk.jmh.annotations.State;
38 import org.openjdk.jmh.annotations.Warmup;
39
40 import java.lang.foreign.MemorySegment.Scope;
41 import java.lang.invoke.MethodHandle;
42 import java.util.concurrent.TimeUnit;
43
44 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
45
46 @BenchmarkMode(Mode.AverageTime)
47 @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
48 @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
49 @State(org.openjdk.jmh.annotations.Scope.Thread)
50 @OutputTimeUnit(TimeUnit.NANOSECONDS)
51 @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" })
52 public class StrLenTest extends CLayouts {
53
54 Arena arena = Arena.ofConfined();
55
56 SegmentAllocator segmentAllocator;
57 SegmentAllocator arenaAllocator = new RingAllocator(arena);
58 SlicingPool pool = new SlicingPool();
59
60 @Param({"5", "20", "100"})
61 public int size;
62 public String str;
63
64 static {
65 System.loadLibrary("StrLen");
66 }
67
68 static final MethodHandle STRLEN;
69
70 static {
71 Linker abi = Linker.nativeLinker();
75
76 @Setup
77 public void setup() {
78 str = makeString(size);
79 segmentAllocator = SegmentAllocator.prefixAllocator(arena.allocate(size + 1, 1));
80 }
81
82 @TearDown
83 public void tearDown() {
84 arena.close();
85 }
86
87 @Benchmark
88 public int jni_strlen() throws Throwable {
89 return strlen(str);
90 }
91
92 @Benchmark
93 public int panama_strlen() throws Throwable {
94 try (Arena arena = Arena.ofConfined()) {
95 MemorySegment segment = arena.allocateFrom(str);
96 return (int)STRLEN.invokeExact(segment);
97 }
98 }
99
100 @Benchmark
101 public int panama_strlen_ring() throws Throwable {
102 return (int)STRLEN.invokeExact(arenaAllocator.allocateFrom(str));
103 }
104
105 @Benchmark
106 public int panama_strlen_pool() throws Throwable {
107 Arena arena = pool.acquire();
108 int l = (int) STRLEN.invokeExact(arena.allocateFrom(str));
109 arena.close();
110 return l;
111 }
112
113 @Benchmark
114 public int panama_strlen_prefix() throws Throwable {
115 return (int)STRLEN.invokeExact(segmentAllocator.allocateFrom(str));
116 }
117
118 @Benchmark
119 public int panama_strlen_unsafe() throws Throwable {
120 MemorySegment address = makeStringUnsafe(str);
121 int res = (int) STRLEN.invokeExact(address);
122 freeMemory(address);
123 return res;
124 }
125
126 static MemorySegment makeStringUnsafe(String s) {
127 byte[] bytes = s.getBytes();
128 int len = bytes.length;
129 MemorySegment address = allocateMemory(len + 1);
130 MemorySegment str = address.asSlice(0, len + 1);
131 str.copyFrom(MemorySegment.ofArray(bytes));
132 str.set(JAVA_BYTE, len, (byte)0);
133 return address;
134 }
135
145 """;
146 return lorem.substring(0, size);
147 }
148
149 static class RingAllocator implements SegmentAllocator {
150 final MemorySegment segment;
151 SegmentAllocator current;
152 long rem;
153
154 public RingAllocator(Arena session) {
155 this.segment = session.allocate(1024, 1);
156 reset();
157 }
158
159 @Override
160 public MemorySegment allocate(long byteSize, long byteAlignment) {
161 if (rem < byteSize) {
162 reset();
163 }
164 MemorySegment res = current.allocate(byteSize, byteAlignment);
165 long lastOffset = res.address() - segment.address() + res.byteSize();
166 rem = segment.byteSize() - lastOffset;
167 return res;
168 }
169
170 void reset() {
171 current = SegmentAllocator.slicingAllocator(segment);
172 rem = segment.byteSize();
173 }
174 }
175
176 static class SlicingPool {
177 final MemorySegment pool = Arena.ofAuto().allocate(1024);
178 boolean isAcquired = false;
179
180 public Arena acquire() {
181 if (isAcquired) {
182 throw new IllegalStateException("An allocator is already in use");
183 }
184 isAcquired = true;
185 return new SlicingPoolAllocator();
|