Skip to content

Commit 4addaf5

Browse files
committed
Add DynamicObject benchmarks for primitive get and set and field access.
1 parent e90a6c4 commit 4addaf5

File tree

1 file changed

+108
-10
lines changed

1 file changed

+108
-10
lines changed

truffle/src/org.graalvm.truffle.benchmark/src/org/graalvm/truffle/benchmark/DynamicObjectBenchmark.java

Lines changed: 108 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,16 @@
4646
import org.graalvm.polyglot.Context;
4747
import org.graalvm.polyglot.Engine;
4848
import org.openjdk.jmh.annotations.Benchmark;
49+
import org.openjdk.jmh.annotations.CompilerControl;
50+
import org.openjdk.jmh.annotations.Param;
4951
import org.openjdk.jmh.annotations.Scope;
5052
import org.openjdk.jmh.annotations.Setup;
5153
import org.openjdk.jmh.annotations.State;
5254
import org.openjdk.jmh.annotations.TearDown;
5355
import org.openjdk.jmh.annotations.Threads;
5456
import org.openjdk.jmh.annotations.Warmup;
5557

58+
import com.oracle.truffle.api.nodes.UnexpectedResultException;
5659
import com.oracle.truffle.api.object.DynamicObject;
5760
import com.oracle.truffle.api.object.Shape;
5861

@@ -63,17 +66,30 @@ public class DynamicObjectBenchmark extends TruffleBenchmark {
6366
private static final int PROPERTY_KEYS_PER_ITERATION = 1000;
6467
static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
6568

66-
static final DynamicObject.GetNode GET_NODE = DynamicObject.GetNode.create();
67-
static final DynamicObject.PutNode PUT_NODE = DynamicObject.PutNode.create();
6869
static final String[] PROPERTY_KEYS = IntStream.range(0, PROPERTY_KEYS_PER_ITERATION).mapToObj(i -> "testKey" + i).toArray(String[]::new);
69-
static final String SOME_KEY = PROPERTY_KEYS[10];
70+
static final String SOME_KEY = PROPERTY_KEYS[0];
71+
static final String SOME_KEY_INT = PROPERTY_KEYS[1];
72+
static final String SOME_KEY_LONG = PROPERTY_KEYS[2];
73+
static final String SOME_KEY_DOUBLE = PROPERTY_KEYS[3];
7074

7175
private static final class MyDynamicObject extends DynamicObject {
7276
private MyDynamicObject(Shape shape) {
7377
super(shape);
7478
}
7579
}
7680

81+
private static final class MyDynamicObjectWithFields extends DynamicObject {
82+
@DynamicField private long lf1;
83+
@DynamicField private long lf2;
84+
@DynamicField private long lf3;
85+
@DynamicField private Object of0;
86+
@DynamicField private Object of1;
87+
88+
MyDynamicObjectWithFields(Shape shape) {
89+
super(shape);
90+
}
91+
}
92+
7793
@State(Scope.Benchmark)
7894
public static class SharedEngineState {
7995
final Engine engine = Engine.newBuilder().allowExperimentalOptions(true).option("engine.Compilation", "false").build();
@@ -107,7 +123,8 @@ public void setup(SharedEngineState shared) {
107123

108124
object = new MyDynamicObject(shared.rootShape);
109125
for (int i = 0; i < PROPERTY_KEYS_PER_ITERATION; i++) {
110-
DynamicObject.PutNode.getUncached().put(object, PROPERTY_KEYS[i], "testValue");
126+
String key = PROPERTY_KEYS[i];
127+
DynamicObject.PutNode.getUncached().put(object, key, "testValue");
111128
}
112129
}
113130

@@ -144,17 +161,98 @@ public void shapeTransitionMapUncontended(SharedEngineState shared, PerThreadCon
144161
}
145162
}
146163

164+
@State(Scope.Benchmark)
165+
public static class AccessNodeBenchState {
166+
167+
@Param({"false", "true"}) boolean field;
168+
169+
Shape rootShape;
170+
DynamicObject object;
171+
172+
final DynamicObject.GetNode getNode = DynamicObject.GetNode.create();
173+
final DynamicObject.PutNode putNode = DynamicObject.PutNode.create();
174+
175+
@Setup
176+
public void setup() {
177+
rootShape = Shape.newBuilder().layout(field ? MyDynamicObjectWithFields.class : MyDynamicObject.class, LOOKUP).build();
178+
object = field ? new MyDynamicObjectWithFields(rootShape) : new MyDynamicObject(rootShape);
179+
180+
for (int i = 0; i < 10; i++) {
181+
String key = PROPERTY_KEYS[i];
182+
if (key.equals(SOME_KEY_INT)) {
183+
DynamicObject.PutNode.getUncached().put(object, key, i);
184+
} else if (key.equals(SOME_KEY_LONG)) {
185+
DynamicObject.PutNode.getUncached().put(object, key, (long) i);
186+
} else if (key.equals(SOME_KEY_DOUBLE)) {
187+
DynamicObject.PutNode.getUncached().put(object, key, (double) i);
188+
} else {
189+
DynamicObject.PutNode.getUncached().put(object, key, "testValue");
190+
}
191+
}
192+
}
193+
}
194+
195+
@Benchmark
196+
@Threads(1)
197+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
198+
public Object get(AccessNodeBenchState state) {
199+
DynamicObject object = state.object;
200+
return state.getNode.getOrDefault(object, SOME_KEY, null);
201+
}
202+
203+
@Benchmark
204+
@Threads(1)
205+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
206+
public int getInt(AccessNodeBenchState state) throws UnexpectedResultException {
207+
DynamicObject object = state.object;
208+
return state.getNode.getIntOrDefault(object, SOME_KEY_INT, null);
209+
}
210+
211+
@Benchmark
212+
@Threads(1)
213+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
214+
public long getLong(AccessNodeBenchState state) throws UnexpectedResultException {
215+
DynamicObject object = state.object;
216+
return state.getNode.getLongOrDefault(object, SOME_KEY_LONG, null);
217+
}
218+
219+
@Benchmark
220+
@Threads(1)
221+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
222+
public double getDouble(AccessNodeBenchState state) throws UnexpectedResultException {
223+
DynamicObject object = state.object;
224+
return state.getNode.getDoubleOrDefault(object, SOME_KEY_DOUBLE, null);
225+
}
226+
227+
@Benchmark
228+
@Threads(1)
229+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
230+
public void put(AccessNodeBenchState state) {
231+
DynamicObject object = state.object;
232+
state.putNode.put(object, SOME_KEY, "updated value");
233+
}
234+
235+
@Benchmark
236+
@Threads(1)
237+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
238+
public void putInt(AccessNodeBenchState state) {
239+
DynamicObject object = state.object;
240+
state.putNode.put(object, SOME_KEY_INT, 42);
241+
}
242+
147243
@Benchmark
148244
@Threads(1)
149-
public Object get(SharedEngineState shared, PerThreadContextState perThread) {
150-
DynamicObject object = perThread.object;
151-
return GET_NODE.getOrDefault(object, SOME_KEY, null);
245+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
246+
public void putLong(AccessNodeBenchState state) {
247+
DynamicObject object = state.object;
248+
state.putNode.put(object, SOME_KEY_LONG, (long) 42);
152249
}
153250

154251
@Benchmark
155252
@Threads(1)
156-
public void put(SharedEngineState shared, PerThreadContextState perThread) {
157-
DynamicObject object = perThread.object;
158-
PUT_NODE.put(object, SOME_KEY, "updated value");
253+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
254+
public void putDouble(AccessNodeBenchState state) {
255+
DynamicObject object = state.object;
256+
state.putNode.put(object, SOME_KEY_DOUBLE, (double) 42);
159257
}
160258
}

0 commit comments

Comments
 (0)