Skip to content

perf(zql): reduce allocations with frozen sentinel and object reuse#5609

Draft
Karavil wants to merge 1 commit intorocicorp:mainfrom
goblinshq:perf/allocation-reduction
Draft

perf(zql): reduce allocations with frozen sentinel and object reuse#5609
Karavil wants to merge 1 commit intorocicorp:mainfrom
goblinshq:perf/allocation-reduction

Conversation

@Karavil
Copy link
Contributor

@Karavil Karavil commented Feb 25, 2026

Note: This PR is part of an upstream contribution effort from the Goblins team (@goblinshq). Co-authored with Claude by Anthropic.

Summary

Reduce GC pressure on the IVM push hot path with two allocation optimizations.

Motivation

During IVM push operations, every source change is propagated to all connected pipelines. For each connection, the current code creates fresh Node and Change objects with new relationships: {} literals. In a workload with 135 IVM pipelines processing ~200 row changes, this creates thousands of short-lived objects per push cycle, increasing GC pressure and pause time.

Similarly, generateWithOverlayInner creates {row, relationships: {}} node objects for every row during fetch, adding more allocation overhead on the fetch hot path.

Changes

  • Add EMPTY_RELATIONSHIPS frozen sentinel at module scope, replacing per-node {} allocation in generateWithOverlayInner (3 sites) and genPush (via reuse objects)
  • Pre-allocate reusable Change objects in genPush (reuseNode, reuseOldNode, reuseAddRemove, reuseEdit) and mutate row fields before yielding, instead of creating new objects per connection per push

Safety

Object reuse in genPush is safe because filterPush consumers are synchronous within the generator chain. Each yield* filterPush(...) completes fully before the next loop iteration mutates the reused objects. There is no concurrent access.

Expected Performance Impact

For 135 IVM pipelines each processing ~200 rows, this eliminates thousands of short-lived {} and Change object allocations per push cycle. The frozen sentinel also enables V8 to share the same hidden class across all nodes, improving inline cache hit rates for downstream consumers that read node.relationships.

Testing

  • All 56 existing memory-source tests pass
  • All 154 existing source tests pass

Stack Order

This PR is part of a stacked series of IVM performance optimizations. Merge in order:

  1. perf(zql): reduce allocations with frozen sentinel and object reuse #5609 (this PR) - Allocation reduction
  2. perf(zql): cache primary index key, pkConstraint, and index lookups #5610 - Index caching
  3. perf(zql): comparator fast paths + compareBounds null fix #5611 - Comparator fast paths
  4. perf(zql): fuse fetch pipeline, add PK fast path, reduce allocations #5612 - Fetch pipeline fusion

Independent PRs (no conflicts): #5607 (BTree iterators), #5608 (Join optimizations)

@vercel
Copy link

vercel bot commented Feb 25, 2026

Someone is attempting to deploy a commit to the Rocicorp Team on Vercel.

A member of the Team first needs to authorize it.

@vercel
Copy link

vercel bot commented Feb 25, 2026

Deployment failed with the following error:

The provided GitHub repository does not contain the requested branch or commit reference. Please ensure the repository is not empty.

@Karavil Karavil force-pushed the perf/allocation-reduction branch 2 times, most recently from d544f50 to 80802a0 Compare February 25, 2026 11:08
…euse

Two allocation reduction optimizations for the IVM push hot path:

1. Shared EMPTY_RELATIONSHIPS sentinel: Replace per-node {} allocation
   with a frozen shared object, reducing GC pressure during fetch and push.

2. Reuse outputChange objects in genPush: Pre-allocate reusable objects
   and mutate row fields before yielding, instead of creating new objects
   per connection.

Object reuse is safe because filterPush consumers are synchronous within
the generator chain.
@Karavil Karavil force-pushed the perf/allocation-reduction branch from 80802a0 to b55846f Compare February 25, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant