Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JohnTortugo/4a78430701869059957c89b21367e235 to your computer and use it in GitHub Desktop.
Save JohnTortugo/4a78430701869059957c89b21367e235 to your computer and use it in GitHub Desktop.
GraalVM Truffle Proxies
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.proxy.ProxyObject;
public class ProxyFieldAccess {
private static final int BENCH_ITERATIONS = 11000;
private static long[] times = new long[BENCH_ITERATIONS];
private static Double[] results = new Double[BENCH_ITERATIONS];
private static final String jsSource = """
(
function simple_sum(order, length) {
let result = 0;
for (var i = 0; i < length; i++) {
result += 3.1415 * order.quantity;
}
return result;
}
)
""";
public static void computeStats(String label, long[] data, int N) {
if (data == null || data.length == 0 || N <= 1 || N > data.length) {
throw new IllegalArgumentException("Invalid input or N too large/small");
}
int startIndex = data.length - N;
double sum = 0.0;
for (int i = startIndex; i < data.length; i++) {
sum += data[i];
}
double average = sum / N;
double varianceSum = 0.0;
for (int i = startIndex; i < data.length; i++) {
double diff = data[i] - average;
varianceSum += diff * diff;
}
double standardDeviation = Math.sqrt(varianceSum / (N - 1)); // sample stdev
double standardError = standardDeviation / Math.sqrt(N);
double zScore = 1.96; // for 95% confidence
double confidenceLow = average - zScore * standardError;
double confidenceHigh = average + zScore * standardError;
System.out.println(label);
System.out.printf("Average: %.2f us%n", average);
System.out.printf("Standard Deviation: %.2f us%n", standardDeviation);
System.out.printf("95%% Confidence Interval: [%.2f, %.2f] us%n", confidenceLow, confidenceHigh);
}
public static class DirectField {
public Integer quantity = 0;
public DirectField(int quantity) {
this.quantity = quantity;
}
}
public static void directFieldAccess() {
final Engine engine = Engine.newBuilder("js")
.allowExperimentalOptions(true)
.option("engine.DynamicCompilationThresholds", "false")
.option("engine.BackgroundCompilation", "false")
.option("engine.OSR", "false")
.build();
var source = Source.newBuilder("js", jsSource, "direct_field_access.js").buildLiteral();
try (var context = Context.newBuilder("js").engine(engine).allowAllAccess(true).build()) {
var function = context.eval(source);
for (int i = 0; i < BENCH_ITERATIONS; i++) {
var order = new DirectField(i);
var start = System.nanoTime();
results[i] = function.execute((Object) order, 100_000).asDouble();
times[i] = (System.nanoTime() - start) / 1_000;
}
}
computeStats("DirectFieldAccess", times, 1000);
}
public static class SingleFieldProxy implements ProxyObject {
Integer quantity = 0;
public SingleFieldProxy(int quantity) {
this.quantity = quantity;
}
@Override
public Object getMember(final String key) {
return quantity;
}
@Override
public Object getMemberKeys() {
return new String[] {"quantity"};
}
@Override
public boolean hasMember(final String key) {
return key.equals("quantity");
}
@Override
public void putMember(final String key, final Value value) {
throw new UnsupportedOperationException("SingleFieldProxy is immutable");
}
}
public static void singleFieldProxyAccess() throws Exception {
final Engine engine = Engine.newBuilder("js")
.allowExperimentalOptions(true)
.option("engine.DynamicCompilationThresholds", "false")
.option("engine.BackgroundCompilation", "false")
.option("engine.OSR", "false")
.build();
var source = Source.newBuilder("js", jsSource, "single_field_proxy_access.js").buildLiteral();
try (var context = Context.newBuilder("js").engine(engine).allowAllAccess(true).build()) {
var function = context.eval(source);
for (int i = 0; i < BENCH_ITERATIONS; i++) {
var order = new SingleFieldProxy(i);
var start = System.nanoTime();
results[i] = function.execute((Object) order, 100_000).asDouble();
times[i] = (System.nanoTime() - start) / 1_000;
}
}
computeStats("SingleFieldProxyAccess", times, 1000);
}
public static void main(String[] args) throws Exception {
System.out.println("-----------------------------------------");
directFieldAccess();
System.out.println("-----------------------------------------");
singleFieldProxyAccess();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment