|
1 | 1 | # Breadth-first GraphQL execution |
2 | 2 |
|
3 | | -_**The original prototype of the core algorithm for Shopify's _GraphQL Cardinal_ engine**_ |
| 3 | +_**The original algorithm proof-of-concept for Shopify's _GraphQL Cardinal_ engine**_ |
4 | 4 |
|
5 | 5 | 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). |
6 | 6 |
|
@@ -37,6 +37,25 @@ This means all field instances are inherently batched as a function of the engin |
37 | 37 |
|
38 | 38 |  |
39 | 39 |
|
| 40 | +## Napkin math |
| 41 | + |
| 42 | +**Assumption:** all GraphQL fields have some non-zero overhead cost associated with their execution. For simplicity, let's round up and say this cost is `1ms`. |
| 43 | + |
| 44 | +**Scenario:** we resolve five fields (_depth_) across a list of 1000 objects (_breadth_). |
| 45 | + |
| 46 | +* In depth-first execution, we call 5000 field resolvers (_depth × breadth_) and incur `5s` of cost. |
| 47 | +* In breadth-first execution, we call 5 field resolvers (_depth-only_) and incur only `5ms`. |
| 48 | + |
| 49 | +Now assume each field operates lazily and returns a promise: |
| 50 | + |
| 51 | +* In depth-first execution, we build and resolve 5000 intermediary promises (_depth × breadth_). |
| 52 | +* In breadth-first execution, we build and resolve 5 intermediary promises (_depth-only_). |
| 53 | + |
| 54 | +Now assume we chain a `.then` onto the lazy promise resolution: |
| 55 | + |
| 56 | +* In depth-first execution, we build and resolve 10,000 intermediary promises (_depth × breadth × 2_). |
| 57 | +* In breadth-first execution, we build and resolve 10 intermediary promises (_depth × 2_). |
| 58 | + |
40 | 59 | ## Prototype usage |
41 | 60 |
|
42 | 61 | This is an extremely early prototype that demonstrates basic breadth-first concepts. It outlines the core engine flow using batched sets, and includes a basic many-to-one promissory workflow. These patterns are being matured for real production use in [graphql-ruby](https://github.com/rmosolgo/graphql-ruby/pull/5509). To experiment with this prototype, you can setup a `GraphQL::BreadthExec::FieldResolver`: |
|
0 commit comments