Skip to content
Open
Prev Previous commit
Next Next commit
improve benchmark
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
  • Loading branch information
chrfwow committed Nov 12, 2025
commit 628eda630d60a5f62b35ac6564b8345895b1e1de
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@
import dev.openfeature.sdk.ObjectHook;
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.StringHook;
import dev.openfeature.sdk.ThreadLocalTransactionContextPropagator;
import dev.openfeature.sdk.Value;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;

/**
* Runs a large volume of flag evaluations on a VM with 1G memory and GC
Expand Down Expand Up @@ -99,55 +98,30 @@ public Optional<EvaluationContext> before(HookContext<Double> ctx, Map<String, O
}

@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
//@BenchmarkMode(Mode.SingleShotTime)
@Fork(jvmArgsAppend = {"-Xmx1024m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseEpsilonGC"})
@Test
public void context() {

OpenFeatureAPI.getInstance().setProviderAndWait(new NoOpProvider());
OpenFeatureAPI.getInstance().setTransactionContextPropagator(new ThreadLocalTransactionContextPropagator());

Map<String, Value> globalAttrs = new HashMap<>();
globalAttrs.put("global", new Value(1));
EvaluationContext globalContext = new ImmutableContext(globalAttrs);
OpenFeatureAPI.getInstance().setEvaluationContext(globalContext);

Client client = OpenFeatureAPI.getInstance().getClient();

Map<String, Value> clientAttrs = new HashMap<>();
clientAttrs.put("client", new Value(2));
client.setEvaluationContext(new ImmutableContext(clientAttrs));

Map<String, Value> transactionAttr = new HashMap<>();
transactionAttr.put("trans", new Value(4));

Map<String, Value> transactionAttr2 = new HashMap<>();
transactionAttr2.put("trans2", new Value(5));

Map<String, Value> invocationAttrs = new HashMap<>();
invocationAttrs.put("invoke", new Value(3));
EvaluationContext invocationContext = new ImmutableContext(invocationAttrs);

for (int i = 0; i < 100; i++) {
OpenFeatureAPI.getInstance().setTransactionContext(new ImmutableContext(transactionAttr));

for (int j = 0; j < 10; j++) {
client.getBooleanValue(BOOLEAN_FLAG_KEY, false);
client.getStringValue(STRING_FLAG_KEY, "default");
client.getIntegerValue(INT_FLAG_KEY, 0);
client.getDoubleValue(FLOAT_FLAG_KEY, 0.0);
client.getObjectDetails(OBJECT_FLAG_KEY, new Value(new ImmutableStructure()), invocationContext);
}
//@Test
public void context(Blackhole blackhole, AllocationBenchmarkState state) {
OpenFeatureAPI.getInstance().setTransactionContext(new ImmutableContext(state.transactionAttr));

for (int j = 0; j < 2; j++) {
blackhole.consume(state.client.getBooleanValue(BOOLEAN_FLAG_KEY, false));
blackhole.consume(state.client.getStringValue(STRING_FLAG_KEY, "default"));
blackhole.consume(state.client.getIntegerValue(INT_FLAG_KEY, 0, state.invocationContext));
blackhole.consume(state.client.getDoubleValue(FLOAT_FLAG_KEY, 0.0));
blackhole.consume(state.client.getObjectDetails(OBJECT_FLAG_KEY, new Value(new ImmutableStructure()),
state.invocationContext));
}

OpenFeatureAPI.getInstance().setTransactionContext(new ImmutableContext(transactionAttr2));
OpenFeatureAPI.getInstance().setTransactionContext(new ImmutableContext(state.transactionAttr2));

for (int j = 0; j < 10; j++) {
client.getBooleanValue(BOOLEAN_FLAG_KEY, false);
client.getStringValue(STRING_FLAG_KEY, "default");
client.getIntegerValue(INT_FLAG_KEY, 0);
client.getDoubleValue(FLOAT_FLAG_KEY, 0.0);
client.getObjectDetails(OBJECT_FLAG_KEY, new Value(new ImmutableStructure()), invocationContext);
}
for (int j = 0; j < 2; j++) {
blackhole.consume(state.client.getBooleanValue(BOOLEAN_FLAG_KEY, false));
blackhole.consume(state.client.getStringValue(STRING_FLAG_KEY, "default"));
blackhole.consume(state.client.getIntegerValue(INT_FLAG_KEY, 0, state.invocationContext));
blackhole.consume(state.client.getDoubleValue(FLOAT_FLAG_KEY, 0.0));
blackhole.consume(state.client.getObjectDetails(OBJECT_FLAG_KEY, new Value(new ImmutableStructure()),
state.invocationContext));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dev.openfeature.sdk.benchmark;

import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.ImmutableContext;
import dev.openfeature.sdk.NoOpProvider;
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.ThreadLocalTransactionContextPropagator;
import dev.openfeature.sdk.Value;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import java.util.HashMap;
import java.util.Map;

@State(Scope.Benchmark)
public class AllocationBenchmarkState {
public final Client client;
public final Map<String, Value> transactionAttr;
public final Map<String, Value> transactionAttr2;
public final EvaluationContext invocationContext;

public AllocationBenchmarkState(){
long start = System.currentTimeMillis();
OpenFeatureAPI.getInstance().setProviderAndWait(new NoOpProvider());
OpenFeatureAPI.getInstance().setTransactionContextPropagator(new ThreadLocalTransactionContextPropagator());
long end = System.currentTimeMillis();
System.out.println("Setup time: " + (end - start) + "ms");
Map<String, Value> globalAttrs = new HashMap<>();
globalAttrs.put("global", new Value(1));
EvaluationContext globalContext = new ImmutableContext(globalAttrs);
OpenFeatureAPI.getInstance().setEvaluationContext(globalContext);

client = OpenFeatureAPI.getInstance().getClient();

Map<String, Value> clientAttrs = new HashMap<>();
clientAttrs.put("client", new Value(2));
client.setEvaluationContext(new ImmutableContext(clientAttrs));

transactionAttr = new HashMap<>();
transactionAttr.put("trans", new Value(4));

transactionAttr2 = new HashMap<>();
transactionAttr2.put("trans2", new Value(5));

Map<String, Value> invocationAttrs = new HashMap<>();
invocationAttrs.put("invoke", new Value(3));
invocationContext = new ImmutableContext(invocationAttrs);

}
}