From 901e66481110374f0858cc6d39dc4a4c5fedaec1 Mon Sep 17 00:00:00 2001 From: Brad Baker Date: Sat, 2 Mar 2024 17:25:05 +1100 Subject: [PATCH 1/3] Raw benchmark on traversing a CF list of objects to traversing a tree of objects --- .../CompletableFuturesBenchmark.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/test/java/benchmark/CompletableFuturesBenchmark.java diff --git a/src/test/java/benchmark/CompletableFuturesBenchmark.java b/src/test/java/benchmark/CompletableFuturesBenchmark.java new file mode 100644 index 0000000000..d49d8e1b24 --- /dev/null +++ b/src/test/java/benchmark/CompletableFuturesBenchmark.java @@ -0,0 +1,109 @@ +package benchmark; + +import com.google.common.collect.ImmutableList; +import graphql.execution.Async; +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.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@State(Scope.Benchmark) +@Warmup(iterations = 2, time = 1) +@Measurement(iterations = 3, time = 10, batchSize = 10) +@Fork(3) +public class CompletableFuturesBenchmark { + + + @Param({"2", "5"}) + public int depth; + public int howMany = 10; + @Setup(Level.Trial) + public void setUp() { + } + + private List> mkCFObjects(int howMany, int depth) { + if (depth <= 0) { + return Collections.emptyList(); + } + ImmutableList.Builder> builder = ImmutableList.builder(); + for (int i = 0; i < howMany; i++) { + CompletableFuture cf = CompletableFuture.completedFuture(mkCFObjects(howMany, depth - 1)); + builder.add(cf); + } + return builder.build(); + } + + private List mkObjects(int howMany, int depth) { + if (depth <= 0) { + return Collections.emptyList(); + } + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < howMany; i++) { + Object obj = mkObjects(howMany, depth - 1); + builder.add(obj); + } + return builder.build(); + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + public void benchmarkCFApproach() { + // make results + List> completableFutures = mkCFObjects(howMany, depth); + // traverse results + traverseCFS(completableFutures); + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + public void benchmarkMaterializedApproach() { + // make results + List objects = mkObjects(howMany, depth); + // traverse results + traverseObjects(objects); + } + + @SuppressWarnings("unchecked") + private void traverseCFS(List> completableFutures) { + for (CompletableFuture completableFuture : completableFutures) { + // and when it's done - visit its child results - which are always immediate on completed CFs + // so this whenComplete executed now + completableFuture.whenComplete((list, t) -> { + List> cfs = (List>) list; + traverseCFS(cfs); + }); + } + } + + @SuppressWarnings("unchecked") + private void traverseObjects(List objects) { + for (Object object : objects) { + List list = (List) object; + traverseObjects(list); + } + } + + public static void main(String[] args) throws Exception { + Options opt = new OptionsBuilder() + .include("benchmark.CompletableFuturesBenchmark") + .forks(1) + .build(); + + new Runner(opt).run(); + } + +} From 2c3cda814eb21937c229972054b52a408e846009 Mon Sep 17 00:00:00 2001 From: Brad Baker Date: Sat, 2 Mar 2024 17:25:24 +1100 Subject: [PATCH 2/3] Raw benchmark on traversing a CF list of objects to traversing a tree of objects- tweak imports --- src/test/java/benchmark/CompletableFuturesBenchmark.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/benchmark/CompletableFuturesBenchmark.java b/src/test/java/benchmark/CompletableFuturesBenchmark.java index d49d8e1b24..d7e06edb64 100644 --- a/src/test/java/benchmark/CompletableFuturesBenchmark.java +++ b/src/test/java/benchmark/CompletableFuturesBenchmark.java @@ -1,7 +1,6 @@ package benchmark; import com.google.common.collect.ImmutableList; -import graphql.execution.Async; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -31,6 +30,7 @@ public class CompletableFuturesBenchmark { @Param({"2", "5"}) public int depth; public int howMany = 10; + @Setup(Level.Trial) public void setUp() { } From 99115a043d912ae8f1716f9074daffc256564f4e Mon Sep 17 00:00:00 2001 From: Brad Baker Date: Sat, 2 Mar 2024 17:39:26 +1100 Subject: [PATCH 3/3] Raw benchmark on traversing a CF list of objects to traversing a tree of objects- desnt need forks --- src/test/java/benchmark/CompletableFuturesBenchmark.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/benchmark/CompletableFuturesBenchmark.java b/src/test/java/benchmark/CompletableFuturesBenchmark.java index d7e06edb64..e22bb1eb7f 100644 --- a/src/test/java/benchmark/CompletableFuturesBenchmark.java +++ b/src/test/java/benchmark/CompletableFuturesBenchmark.java @@ -100,7 +100,6 @@ private void traverseObjects(List objects) { public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() .include("benchmark.CompletableFuturesBenchmark") - .forks(1) .build(); new Runner(opt).run();