From bf441dee9ec931196741347bced51c42fd483ff6 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sun, 20 Apr 2025 20:26:23 +1000 Subject: [PATCH 1/4] Large in memory query benchmark --- .../LargeInMemoryQueryBenchmark.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/test/java/benchmark/LargeInMemoryQueryBenchmark.java diff --git a/src/test/java/benchmark/LargeInMemoryQueryBenchmark.java b/src/test/java/benchmark/LargeInMemoryQueryBenchmark.java new file mode 100644 index 0000000000..f7f58dacb6 --- /dev/null +++ b/src/test/java/benchmark/LargeInMemoryQueryBenchmark.java @@ -0,0 +1,139 @@ +package benchmark; + +import graphql.GraphQL; +import graphql.schema.GraphQLSchema; +import graphql.schema.idl.RuntimeWiring; +import graphql.schema.idl.SchemaGenerator; +import graphql.schema.idl.SchemaParser; +import graphql.schema.idl.TypeDefinitionRegistry; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.profile.GCProfiler; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring; + +/** + * This benchmark is an attempt to have a large in memory query that involves only sync work but lots of + * data fetching invocation + *

+ * It can also be run in a forever mode say if you want to connect a profiler to it say + */ +@State(Scope.Benchmark) +@Warmup(iterations = 2, time = 5) +@Measurement(iterations = 2) +@Fork(2) +public class LargeInMemoryQueryBenchmark { + + GraphQL graphQL; + volatile boolean shutDown; + + @Setup(Level.Trial) + public void setUp() { + shutDown = false; + graphQL = buildGraphQL(); + } + + @TearDown(Level.Trial) + public void tearDown() { + shutDown = true; + } + + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @OutputTimeUnit(TimeUnit.SECONDS) + public Object benchMarkSimpleQueriesThroughput() { + return runManyQueriesToCompletion(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.SECONDS) + public Object benchMarkSimpleQueriesAvgTime() { + return runManyQueriesToCompletion(); + } + + + public static void main(String[] args) throws Exception { + // just to make sure it's all valid before testing + runAtStartup(); + + Options opt = new OptionsBuilder() + .include("benchmark.LargeInMemoryQueryBenchmark") + .addProfiler(GCProfiler.class) + .build(); + + new Runner(opt).run(); + } + + private static void runAtStartup() { + + LargeInMemoryQueryBenchmark complexQueryBenchmark = new LargeInMemoryQueryBenchmark(); + BenchmarkUtils.runInToolingForSomeTimeThenExit( + complexQueryBenchmark::setUp, + complexQueryBenchmark::runManyQueriesToCompletion, + complexQueryBenchmark::tearDown + + ); + } + + + private Object runManyQueriesToCompletion() { + return graphQL.execute( + "query {\n" + + "\n" + + " giveMeLargeResponse {\n" + + " someValue\n" + + " }\n" + + "}" + ); + } + + private static final List manyObjects = IntStream + .range(0, 10_000_000) + .mapToObj(i -> new SomeWrapper("value #" + i)) + .collect(Collectors.toList()); + + public static class SomeWrapper { + String someValue; + + public SomeWrapper(String someValue) { + this.someValue = someValue; + } + } + + private GraphQL buildGraphQL() { + TypeDefinitionRegistry typeDefinitionRegistry = new SchemaParser().parse("\n" + + "type Query {\n" + + " giveMeLargeResponse: [SomeWrapper]\n" + + "}\n" + + "type SomeWrapper {\n" + + " someValue: String\n" + + "}\n" + ); + RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring() + .type(newTypeWiring("Query") + .dataFetcher("giveMeLargeResponse", env -> manyObjects)) + .build(); + GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeDefinitionRegistry, wiring); + return GraphQL.newGraphQL(schema).build(); + } +} From b4f07cb826a1e6e25cb7119649b9b4123c579a31 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sun, 20 Apr 2025 20:46:16 +1000 Subject: [PATCH 2/4] Large in memory query benchmark - moving --- .../{benchmark => graphql}/LargeInMemoryQueryBenchmark.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/test/java/{benchmark => graphql}/LargeInMemoryQueryBenchmark.java (97%) diff --git a/src/test/java/benchmark/LargeInMemoryQueryBenchmark.java b/src/test/java/graphql/LargeInMemoryQueryBenchmark.java similarity index 97% rename from src/test/java/benchmark/LargeInMemoryQueryBenchmark.java rename to src/test/java/graphql/LargeInMemoryQueryBenchmark.java index f7f58dacb6..d4baae7236 100644 --- a/src/test/java/benchmark/LargeInMemoryQueryBenchmark.java +++ b/src/test/java/graphql/LargeInMemoryQueryBenchmark.java @@ -1,6 +1,6 @@ -package benchmark; +package graphql; -import graphql.GraphQL; +import benchmark.BenchmarkUtils; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; @@ -77,7 +77,7 @@ public static void main(String[] args) throws Exception { runAtStartup(); Options opt = new OptionsBuilder() - .include("benchmark.LargeInMemoryQueryBenchmark") + .include("graphql.LargeInMemoryQueryBenchmark") .addProfiler(GCProfiler.class) .build(); From 61f177ce4f96e6f7ffac9eaba7290fc65439daa3 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sun, 20 Apr 2025 20:53:45 +1000 Subject: [PATCH 3/4] Large in memory query benchmark - moving class --- .../java/benchmark}/LargeInMemoryQueryBenchmark.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/{test/java/graphql => jmh/java/benchmark}/LargeInMemoryQueryBenchmark.java (97%) diff --git a/src/test/java/graphql/LargeInMemoryQueryBenchmark.java b/src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java similarity index 97% rename from src/test/java/graphql/LargeInMemoryQueryBenchmark.java rename to src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java index d4baae7236..f7f58dacb6 100644 --- a/src/test/java/graphql/LargeInMemoryQueryBenchmark.java +++ b/src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java @@ -1,6 +1,6 @@ -package graphql; +package benchmark; -import benchmark.BenchmarkUtils; +import graphql.GraphQL; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; @@ -77,7 +77,7 @@ public static void main(String[] args) throws Exception { runAtStartup(); Options opt = new OptionsBuilder() - .include("graphql.LargeInMemoryQueryBenchmark") + .include("benchmark.LargeInMemoryQueryBenchmark") .addProfiler(GCProfiler.class) .build(); From f1730ccc4d666deb62169cc6841e4f56e91d7c51 Mon Sep 17 00:00:00 2001 From: bbaker Date: Tue, 22 Apr 2025 13:32:53 +1000 Subject: [PATCH 4/4] Large in memory query benchmark - moving class to performance --- .../LargeInMemoryQueryPerformance.java} | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) rename src/jmh/java/{benchmark/LargeInMemoryQueryBenchmark.java => performance/LargeInMemoryQueryPerformance.java} (94%) diff --git a/src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java b/src/jmh/java/performance/LargeInMemoryQueryPerformance.java similarity index 94% rename from src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java rename to src/jmh/java/performance/LargeInMemoryQueryPerformance.java index f7f58dacb6..924c4ee9d0 100644 --- a/src/jmh/java/benchmark/LargeInMemoryQueryBenchmark.java +++ b/src/jmh/java/performance/LargeInMemoryQueryPerformance.java @@ -1,5 +1,6 @@ -package benchmark; +package performance; +import benchmark.BenchmarkUtils; import graphql.GraphQL; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; @@ -40,7 +41,7 @@ @Warmup(iterations = 2, time = 5) @Measurement(iterations = 2) @Fork(2) -public class LargeInMemoryQueryBenchmark { +public class LargeInMemoryQueryPerformance { GraphQL graphQL; volatile boolean shutDown; @@ -77,7 +78,7 @@ public static void main(String[] args) throws Exception { runAtStartup(); Options opt = new OptionsBuilder() - .include("benchmark.LargeInMemoryQueryBenchmark") + .include("performance.LargeInMemoryQueryBenchmark") .addProfiler(GCProfiler.class) .build(); @@ -86,7 +87,7 @@ public static void main(String[] args) throws Exception { private static void runAtStartup() { - LargeInMemoryQueryBenchmark complexQueryBenchmark = new LargeInMemoryQueryBenchmark(); + LargeInMemoryQueryPerformance complexQueryBenchmark = new LargeInMemoryQueryPerformance(); BenchmarkUtils.runInToolingForSomeTimeThenExit( complexQueryBenchmark::setUp, complexQueryBenchmark::runManyQueriesToCompletion,