You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,22 +6,22 @@ _**The original prototype of the core algorithm for Shopify's _GraphQL Cardinal_
6
6
7
7
GraphQL requests have two dimensions: _depth_ and _breadth_. The depth dimension is finite as defined by the request document, while the breadth dimension scales by the width of the response data (and can grow extremely large).
8
8
9
-

9
+

10
10
11
-
Traditional GraphQL implementations execute _depth-first_, which resolves every field of every object in the response individually, making resolver overhead (resolver calls, tracing, intermediary promises) scale by **depth × breadth**. To execute _breadth-first_, we instead resolve each selection position spanning depth only once with an aggregated breadth of objects. Now resolver overhead only scales by the static depth of the document, and processing list repetitions becomes considerably faster.
11
+
Traditional GraphQL implementations execute _depth-first_, which resolves every field of every object in the response individually, making resolver overhead (resolver calls, tracing, intermediary promises) scale by **depth × breadth**. To execute _breadth-first_, we instead resolve each selection depth only once with an aggregated breadth of objects, so resolver overhead now scales by **depth-only**. This makes processing list repetitions considerably faster.
12
12
13
13
```shell
14
-
graphql-ruby: 140002 resolvers
14
+
graphql-ruby (depth): 140002 resolvers
15
15
1.087 (± 0.0%) i/s (919.76 ms/i) - 6.000 in 5.526807s
16
16
graphql-breadth_exec 140002 resolvers
17
17
21.314 (± 9.4%) i/s (46.92 ms/i) - 108.000 in 5.095015s
Breadth-first resolvers look a little different than we're used to: they recieve `objects` and return a mapped set.
27
27
@@ -31,7 +31,7 @@ def resolve(objects, args, cxt)
31
31
end
32
32
```
33
33
34
-
In effect, all field instances are automatically batched without the use of DataLoader. However, we frequently need to batch work across field instances (ex: same field using different aliases, different fields sharing a query, etc.), which still involves DataLoader promises. Breadth is still remarkably efficient at this because it can bind many object loads to a single promise, versus resolving a promise per loaded object
34
+
This means all field instances are inherently batched as a function of the engine without using DataLoader promise patterns. However, promises are still relevant for batching work _across field instances_ (ie: same field using different aliases, or different fields sharing a query, etc.), and they can be considerably more efficient in breadth execution by binding many objects to a single promise rather than generating a promise per object:
0 commit comments