Skip to content

fix(executor): stop retaining duplicate copies of loop block outputs - #8618

Closed
waleedlatif1 wants to merge 5 commits into
stagingfrom
fix/executor-loop-log-output-sharing
Closed

waleedlatif1 wants to merge 5 commits into
stagingfrom
fix/executor-loop-log-output-sharing

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Long-running loops grew the worker heap linearly with block executions until the process was OOM-killed. Each iteration's output was retained as separate structural copies for the whole run: blockLog.output (a deep copy made only to drop the rarely-present childTraceSpans key) and the loop's allIterationOutputs (a second rebuild by compactSubflowResults of an output that compactBlockOutput had already compacted)
  • filterHiddenOutputKeys is now copy-on-write: an unchanged plain object/array is returned as-is and a copy starts only at the first changed child. Non-plain prototypes (Date, class instances, null-prototype objects) are still rebuilt, so the output is unchanged
  • compactEntries reuses unchanged plain subtrees only for compactSubflowResults, whose inputs are already-compacted state outputs. Reusing everywhere was measured and rejected: retaining raw handler (JSON.parse) objects instead of the rebuilt ones costs ~4x heap on wide rows
  • getJsonByteSize (moved to lib/logs/execution/json-byte-size.ts) tracks ancestors only. Its never-cleared seen-set counted a shared subtree once while JSON.stringify writes it per occurrence, so with shared outputs the 3 MB inline execution-data check would have undercounted
  • displayOutput for block-complete callbacks reuses blockLog.output via a shallow copy instead of re-walking the output (top level stays separate because streaming later writes token/cost keys onto the log)

Type of Change

  • Bug fix

Testing

  • Executor-level benchmark (real DAGExecutor, for loop, mocked handler returning fresh table-shaped output; GC-forced live heap at the last iteration, repeated runs identical):
    • 40 cols × 360 rows, 150 iterations: 44 MB → 19–23 MB
    • 400 cols × 144 rows, 40 iterations: 31 MB → 9–12 MB
    • 10 cols × 1440 rows, 150 iterations: 84 MB → 42–45 MB; wall time 9.4s → 8.5s
  • Equivalence checks against the previous implementations (27 cases: Date, Map/Set, Buffer/typed arrays, class instances with getters, null-prototype, own __proto__ key, sparse arrays, symbol/non-enumerable keys, hidden keys at any depth, UserFile base64 stripping, nested finalBlockLogs): identical JSON and structure
  • New json-byte-size.test.ts: shared-subtree cases fail on the pre-fix seen-set and pass after
  • Root bun run test (all workspaces), bun run lint, bun run type-check, bun run check:audits, check-block-registry.ts origin/staging, docs-manifest:check

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 5, 2026 9:20am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Optimizes memory use in execution logging by sharing object references.

The PR appears safe to merge; no actionable new issue or outstanding previous finding was identified.

Summary

This PR reduces duplicate retention of loop block outputs by reusing unchanged, already-compacted subtrees. It also updates execution-log byte counting to count shared subtrees at each occurrence and adds regression tests for sharing and size measurement.

  • The previously requested identity tests are present, and that thread is resolved.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Block output] --> B[Compacted state output]
  B --> C[Copy-on-write log filtering]
  B --> D[Loop result aggregation]
  C --> E[Block log and callback]
  D --> F[Shared subtrees]
  E --> G[Execution-log size check]
  F --> G
Loading

Reviews (5) · Last reviewed commit: "fix(logs): measure execution data iterat..."

Comment thread apps/sim/lib/execution/payloads/serializer.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 8 files

Re-trigger cubic

Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
Comment thread apps/sim/lib/execution/payloads/serializer.ts
Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 8 files

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
Comment thread apps/sim/lib/logs/execution/json-byte-size.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Closing as superseded: every change in this PR landed on staging via #8620 (squash commit b2c5b76), which was built on top of this branch and merged first. All files touched here match staging exactly, apart from #8620's later refinements to json-byte-size.ts and the PII step in logger.ts.

@waleedlatif1
waleedlatif1 deleted the fix/executor-loop-log-output-sharing branch October 5, 2026 16:15

This branch was previously deployed

1 inactive deployment
Preview — 546b030c Deployed Oct 5, 2026 by vercel[bot]
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