Skip to content

perf(storage): stop forcing a full GC after every part - #9

Open
chenrui333 wants to merge 1 commit into
review-base/upstream-devfrom
perf/no-forced-gc
Open

chenrui333 wants to merge 1 commit into
review-base/upstream-devfrom
perf/no-forced-gc

Conversation

@chenrui333

Copy link
Copy Markdown
Owner

Review copy of a proposed upstream change, based on falcondev-oss/github-actions-cache-server@dev (6ae06c2). Upstream accepts pull requests from collaborators only, so this branch is offered through an upstream issue.

streamParts() awaits globalThis.gc() after every part, pumpPartsToStreams() once more at the end, and the image starts Node with --expose-gc. Every part of every unmerged restore and streaming merge therefore runs a synchronous full mark-compact on the event loop. With BuildKit's ~1 MiB parts that caps all concurrent first restores combined at roughly one part per GC pause, and the pause grows with the heap, so more concurrent restores make each of them slower.

The calls were added for memory (falcondev-oss#182), but memory no longer depends on them: the upload route lets storage pace the body (falcondev-oss#275) and the download route pipes with backpressure (falcondev-oss#282). The bytes in flight are bounded by stream high-water marks and become ordinary garbage that V8 collects incrementally.

This PR removes both calls, the --expose-gc flag and the startup warning that asked for it.

Benchmark

Built dev (nitropack build), one worker, SQLite + filesystem, on an M-series Mac. Each run seeds N unmerged entries of 96 × 1 MiB parts, then restores all of them concurrently (first restore = tee + merge), then again after the merges (warm). Every restore is SHA-256 checked (all passed). Peak RSS is the max over the primary and worker processes, sampled every 200 ms. Interleaved runs:

N concurrent first restores Build Cold time (s) Cold MiB/s Peak RSS (MiB)
16 dev, --expose-gc (as shipped) 15.3 / 14.4 / 14.9 100 / 107 / 103 278 / 311 / 294
16 this PR 1.4 / 2.6 1079 / 588 352 / 343
32 dev, --expose-gc 31.7 / 40.5 97 / 76 339 / 238
32 this PR 9.7 / 12.1 316 / 255 351 / 342

Running dev without --expose-gc (so globalThis.gc is undefined) matched this PR: 2.0 / 3.2 / 2.7 s at N = 16. Warm (merged) restores don't call gc() and were the same for both builds (~1 GiB/s).

Memory stays bounded without forced GC: peak RSS is ~350 MiB at both 16 and 32 concurrent restores, about 50 MiB above the forced-GC build, and does not grow with concurrency.

pnpm test:run (sqlite + filesystem) passes as on dev; type-check and eslint are clean.

Notes

`streamParts()` awaited `globalThis.gc()` after every part, and the image
starts Node with `--expose-gc`, so every part of every unmerged restore and
streaming merge ran a synchronous full mark-compact on the event loop. With
~1 MiB parts (BuildKit) that caps all concurrent first restores combined at
roughly one part per GC pause, and the pause grows with the heap, so more
concurrent restores make every one of them slower.

Memory no longer depends on it: the upload route lets storage pace the body
(falcondev-oss#275) and the download route pipes with backpressure (falcondev-oss#282), so the bytes
in flight are bounded by stream high-water marks and become ordinary
garbage that V8 collects incrementally.

Remove both calls, the `--expose-gc` flag and the startup warning about it.

Signed-off-by: Rui Chen <rui@chenrui.dev>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T20:27:52.692569Z 6ddb082 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chenrui333

Copy link
Copy Markdown
Owner Author

@codex review

1 similar comment
@chenrui333

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 6ddb082d61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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