Skip to content

Commit f5d7d23

Browse files
committed
cleanup and comments
1 parent 49fbe60 commit f5d7d23

File tree

5 files changed

+65
-242
lines changed

5 files changed

+65
-242
lines changed

src/jmh/java/benchmark/IntMapBenchmark.java

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/jmh/java/performance/DataLoaderPerformance.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import graphql.ExecutionInput;
55
import graphql.ExecutionResult;
66
import graphql.GraphQL;
7+
import graphql.execution.instrumentation.dataloader.DataLoaderDispatchingContextKeys;
78
import graphql.schema.DataFetcher;
89
import graphql.schema.GraphQLSchema;
910
import graphql.schema.idl.RuntimeWiring;
@@ -14,16 +15,28 @@
1415
import org.dataloader.DataLoader;
1516
import org.dataloader.DataLoaderFactory;
1617
import org.dataloader.DataLoaderRegistry;
18+
import org.openjdk.jmh.annotations.Benchmark;
19+
import org.openjdk.jmh.annotations.BenchmarkMode;
20+
import org.openjdk.jmh.annotations.Fork;
21+
import org.openjdk.jmh.annotations.Measurement;
22+
import org.openjdk.jmh.annotations.Mode;
23+
import org.openjdk.jmh.annotations.OutputTimeUnit;
1724
import org.openjdk.jmh.annotations.Scope;
1825
import org.openjdk.jmh.annotations.Setup;
1926
import org.openjdk.jmh.annotations.State;
27+
import org.openjdk.jmh.annotations.Warmup;
2028
import org.openjdk.jmh.infra.Blackhole;
2129

2230
import java.util.List;
2331
import java.util.Map;
2432
import java.util.concurrent.CompletableFuture;
33+
import java.util.concurrent.TimeUnit;
2534
import java.util.stream.Collectors;
2635

36+
@State(Scope.Benchmark)
37+
@Warmup(iterations = 2, time = 5)
38+
@Measurement(iterations = 3)
39+
@Fork(2)
2740
public class DataLoaderPerformance {
2841

2942
static Owner o1 = new Owner("O-1", "Andi", List.of("P-1", "P-2", "P-3"));
@@ -560,6 +573,9 @@ public void setup() {
560573

561574
}
562575

576+
@Benchmark
577+
@BenchmarkMode(Mode.AverageTime)
578+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
563579
public void executeRequestWithDataLoaders(MyState myState, Blackhole blackhole) {
564580
DataLoader ownerDL = DataLoaderFactory.newDataLoader(ownerBatchLoader);
565581
DataLoader petDL = DataLoaderFactory.newDataLoader(petBatchLoader);
@@ -571,7 +587,7 @@ public void executeRequestWithDataLoaders(MyState myState, Blackhole blackhole)
571587
.dataLoaderRegistry(registry)
572588
// .profileExecution(true)
573589
.build();
574-
// executionInput.getGraphQLContext().put(DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_CHAINING, true);
590+
executionInput.getGraphQLContext().put(DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_CHAINING, true);
575591
ExecutionResult execute = myState.graphQL.execute(executionInput);
576592
// ProfilerResult profilerResult = executionInput.getGraphQLContext().get(ProfilerResult.PROFILER_CONTEXT_KEY);
577593
// System.out.println("execute: " + execute);

src/main/java/graphql/execution/instrumentation/dataloader/LevelMap.java

Lines changed: 0 additions & 79 deletions
This file was deleted.

src/main/java/graphql/execution/instrumentation/dataloader/PerLevelDataLoaderDispatchStrategy.java

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,16 @@ public StateForLevel(@Nullable DataLoaderInvocation dataLoaderInvocation,
7272
StateForLevel currentState = currentStateRef.get();
7373

7474

75-
boolean dispatchingStarted = currentState != null && currentState.dispatchingStarted;
76-
boolean dispatchingFinished = currentState != null && currentState.dispatchingFinished;
77-
boolean currentlyDelayedDispatching = currentState != null && currentState.currentlyDelayedDispatching;
75+
boolean dispatchingStarted = false;
76+
boolean dispatchingFinished = false;
77+
boolean currentlyDelayedDispatching = false;
78+
79+
if (currentState != null) {
80+
dispatchingStarted = currentState.dispatchingStarted;
81+
dispatchingFinished = currentState.dispatchingFinished;
82+
currentlyDelayedDispatching = currentState.currentlyDelayedDispatching;
83+
84+
}
7885

7986
if (!chained) {
8087
if (normalDispatchOrDelayed) {
@@ -107,10 +114,16 @@ public boolean newDataLoaderInvocation(DataLoaderInvocation dataLoaderInvocation
107114
while (true) {
108115
StateForLevel currentState = currentStateRef.get();
109116

117+
boolean dispatchingStarted = false;
118+
boolean dispatchingFinished = false;
119+
boolean currentlyDelayedDispatching = false;
110120

111-
boolean dispatchingStarted = currentState != null && currentState.dispatchingStarted;
112-
boolean dispatchingFinished = currentState != null && currentState.dispatchingFinished;
113-
boolean currentlyDelayedDispatching = currentState != null && currentState.currentlyDelayedDispatching;
121+
if (currentState != null) {
122+
dispatchingStarted = currentState.dispatchingStarted;
123+
dispatchingFinished = currentState.dispatchingFinished;
124+
currentlyDelayedDispatching = currentState.currentlyDelayedDispatching;
125+
126+
}
114127

115128
// we need to start a new delayed dispatching if
116129
// the normal dispatching is finished and there is no currently delayed dispatching for this level
@@ -135,6 +148,35 @@ public void clear() {
135148

136149
private static class CallStack {
137150

151+
/**
152+
* We track three things per level:
153+
* - the number of execute object calls
154+
* - the number of object completion calls
155+
* - if the level is already dispatched
156+
* <p/>
157+
* The number of execute object calls is the number of times the execution
158+
* of a field with sub selection (meaning it is an object) started.
159+
* <p/>
160+
* For each execute object call there will be one matching object completion call,
161+
* indicating that the all fields in the sub selection have been fetched AND completed.
162+
* Completion implies the fetched value is "resolved" (CompletableFuture is completed if it was a CF)
163+
* and it the engine has processed it and called any needed subsequent execute object calls (if the result
164+
* was none null and of Object of [Object] (or [[Object]] etc).
165+
* <p/>
166+
* Together we know a that a level is ready for dispatch if:
167+
* - the parent was dispatched
168+
* - the #executeObject == #completionFinished in the grandparent level.
169+
* <p/>
170+
* The second condition implies that all execute object calls in the parent level happened
171+
* which again implies that all fetch fields in the current level have happened.
172+
* <p/>
173+
* For the first level we track only if all expected fetched field calls have happened.
174+
*/
175+
176+
/**
177+
* The whole algo is impleted lock free and relies purely on CAS methods to handle concurrency.
178+
*/
179+
138180
static class StateForLevel {
139181
private final int happenedCompletionFinishedCount;
140182
private final int happenedExecuteObjectCalls;

src/test/groovy/graphql/execution/instrumentation/dataloader/LevelMapTest.groovy

Lines changed: 0 additions & 113 deletions
This file was deleted.

0 commit comments

Comments
 (0)