Benchmark generator API, fix performance of nested all calls - #64206
Conversation
… task structures And update the executor to not nest and install handle `all` similarly to `defer`, for performance reasons.
There was a problem hiding this comment.
🟡 Changes recommended
The updated test uses api["client"] to access a private field, which will fail TypeScript type-checking unless it’s explicitly cast/suppressed.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors the sync generator executor so all(...) no longer behaves like a nested “mini-executor”; instead, all yields a discriminated host message and the host executor performs group orchestration, improving performance for deeply nested joins. It also adds/updates benchmark coverage (including a new generators benchmark variant generated from the async benchmark source) and expands tests around batching/ordering/error semantics.
Changes:
- Reworked
all/executeRequestGeneratorsso nestedallgroups are handled by the host executor via__allhost messages (reducing overhead from nested executor layers). - Added extensive sync generator batching tests for nested joins, ordering, cancellation, and error propagation; added a generator benchmark smoke test.
- Introduced a generated “generators” benchmark variant and updated the sync generation script to support
@generators:*directives.
File summaries
| File | Description |
|---|---|
| packages/typescript/test/sync/api-generators.test.ts | Adds new behavioral tests for __all/__defer, join semantics, batching observation, and runs generator benchmarks in single-iteration mode. |
| packages/typescript/test/generators/api.bench.ts | New auto-generated benchmark suite for the generator API. |
| packages/typescript/test/async/api.bench.ts | Adds @generators:* directives to drive generation of the generator benchmark variant. |
| packages/typescript/test/api.bench.ts | Includes the generator benchmark suite when running the consolidated benchmark entrypoint. |
| packages/typescript/test/api-comparison.bench.ts | New benchmark comparing sync/async/generator APIs and executor-only overhead across all nesting depths. |
| packages/typescript/src/api/sync/generatorSupport.ts | Core implementation change: all now yields __all and group orchestration/dedup/cancellation is implemented in executeRequestGenerators. |
| packages/typescript/src/api/sync/api.ts | Re-exports AllAPIRequestGenerator from generator support. |
| packages/typescript/src/api/async/api.ts | Updates sync-only export comment to include AllAPIRequestGenerator for directive-driven generation. |
| packages/typescript/scripts/generateSync.ts | Adds “generators” variant support and new directive handling (@generators: replacements and generators-only/skip blocks). |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
…messages and unwrapping `all` where possible is good
|
Ah Andrew Branch (@andrewbranch) apologies, I found some other performance gains I could apply. Turns out using a class that implements the iterator protocol for the hoisted messages is a bit faster than a wrapping native generator - presumably because the runtime doesn't need to manage any continuation state. It's not as huge as the initial change, but it's a meaningful improvement to API throughput in the heavy presence of |
Fixes an issue Titian Cernicova-Dragomir (@dragomirtitian) reported where on large batches he was seeing increased performance overhead of nested
allcalls in the generator executor. Perf tests proved it out that every layer ofallnesting withallas a near-full executor in its own right was something like 30% reduced performance over inlining into the parent, stacking with increased depth. Presumably the extra generator states were difficult for the runtime to manage effectively or inline compared to managing it ourselves.This change is basically deferring the
allgroup handling to the host executor, which fixes that performance issue and makes the performance stable with highly nestedallcalls.