Repository navigation
perf: smaller release archives, less memory in long sessions - #72
Conversation
- The TUI's tool component kept the whole result it was given, structuredContent too: for bash, the command's output up to 1 MB (the content shows 50 KB), for the rest of the session. It now keeps content, details, isError and durationMs, which is all it draws. - A file read again unchanged gives the string the earlier read gave (detachSharedString: the latest 2M characters of read outputs, by content), so the session holds it once. Live heap after a full collection (macOS, 0.9.5 runtime), long_session.py with every prompt also running a command with 1.3 MB of output, 30 prompts: 91.4 MB -> 27.9 MB. Standard long_session.py (the same four files read every prompt), 60 prompts: 40.6 MB -> 13.6 MB.
…for x86-64 - The docs' PNG files (2.5 MB; the model reads the text, and a terminal shows no picture) are not shipped. - The x86-64 .tar.xz archives go through xz's x86 filter first (call targets made relative): 2% smaller, and every xz since 5.0 unpacks it. Not the ARM64 filter, which xz and libarchive before 5.4 cannot unpack. linux-x64 .tar.xz: 58.68 MB -> 55.17 MB (-6.0%).
The same kind of .zip (deflate, no Zip64), which install.ps1, npm/install.cjs and Expand-Archive unpack: pi-bolt.exe 93.9 MB -> 90.7 MB (-3.4%) at -mx=7, about a minute more per archive. Without 7-Zip, .NET's ZipFile as before.
There was a problem hiding this comment.
If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.
Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Update after merging origin/pi-bolt (#69, #73): #69 fixed item 1 at the call site (
interactive-mode.ts,tool_execution_endpasses only the drawn fields). The component-level copy of the same fix and its test are removed from this branch; #69's stays. Items 2 and 3 are unchanged. Re-measured on the merged branch (macOS, 0.9.5 runtime, live heap after a full collection): bash long session at 30 prompts 17.8 MB (heap 14.4 + strings 3.4), standard long session at 60 prompts 13.6 MB (heap 11.6 + strings 2.0); 0.9.5: 91.4 MB and 40.6 MB. The CI numbers below are from before the merge (this branch alone).Smaller downloads and less memory in long sessions, without changing the executable or the engine. Measured against 0.9.5's release files.
1. Tool results held twice in the TUI (packages/coding-agent): now #69's fix
Problem.
ToolExecutionComponent.updateResult()kept the whole result object it got fromtool_execution_end,structuredContentincluded. Forbashthat is the command's output up to 1 MB (STRUCTURED_OUTPUT_MAX_BYTES), while the content shows 50 KB. The component lives for the whole session, so every command with large output (builds, tests, logs) stayed in memory to the end. The component draws onlycontent,details,isErroranddurationMs, and renderers receive only{ content, details }.Example: 30 prompts that each run
seq N 200000(1.3 MB of output) plus three file reads. Live heap after a full collection (macOS,heapStats()from an extension): heap 51.2 MB + external strings 40.2 MB.Fix. The component keeps only the four fields it draws. Result: heap 19.5 MB + external strings 8.4 MB (91.4 MB -> 27.9 MB).
2. The same file read again is held once (packages/coding-agent)
Problem. Each
readreturns a new string, even when the file did not change. A session that reads the same file again holds one copy per read. Inbench/long_session.py(the same four files every prompt), 7.3 MB of the 8.5 MB of strings at 30 prompts were such copies.Fix.
detachSharedString()returns the copy it gave out before for equal content. It keeps the latest outputs of 4K+ characters, up to 2M characters, and is used byreadin place ofdetachString(). Only identity changes; the text is the same. Live heap after a full collection, 60 prompts: 40.6 MB -> 13.6 MB. In real sessions the gain is smaller: it applies only to re-reads of unchanged files.3. Smaller archives (scripts)
docs/images(2.5 MB of PNG) is no longer shipped. The model reads the text and a terminal shows no pictures. The only picture the docs embed has alt text.build-pi.shandbuild-pi.ps1remove it. All.mddocs stay, including the onesdoctorpoints at (Release tarballs omit docs/PLUGINS.md, which pi-bolt doctor and the docs point at #63)..tar.xzgoes through xz's x86 BCJ filter first (xz -T0 --x86 --lzma2=preset=9e), which makes 2% of the remaining size go away. Every xz and liblzma since 5.0 (2010) unpacks it, andinstall.shrunsxz -dcortar. ARM64 does not use the ARM64 filter, because xz and libarchive older than 5.4 cannot unpack it (Ubuntu 22.04, macOS's tar)..zipis written with 7-Zip's deflate (-mx=7) where 7-Zip is installed (GitHub's Windows runners), otherwise with .NET's as before. It is the same format: deflate, no Zip64.npm/install.cjs's zip reader unpacks it byte-identical (checked locally on a 7-Zip zip of 0.9.5's tree). The release workflow unpacks each archive withExpand-Archiveand runs its tests on that.Numbers (0.9.5 release -> this branch)
CI run 39328730913 (
bench/lighter-096): this branch's Pi on 0.9.5's runtimes, packaged aspackage-release.shdoes, againstgh release download bolt-v0.9.5."Own" is Private_Dirty on Linux and the physical footprint on macOS. Long-session figures are single runs, sampled every 10 prompts, so they show GC timing too. The live-heap figures above, taken after a full collection, are the steady measure.
-mx=7(local, 0.9.5's exe), plus 2.4 MB of compressed PNGs. Not yet measured from a release run.Checks
install.shinstalls this branch's linux-x64 archive (x86 filter) and its linux-arm64 archive from a served folder. The installed tree is identical to the archive's, andpi --versionruns (CI, both Linux runners).download failed: .../SHA256SUMS). The macOS archive format is unchanged apart from the missing PNGs.pi-bolt doctorchecks only that SHA256SUMS lists the archive names, which are unchanged.pi-bolt updaterunsinstall.sh.bench/e2e_tools.pyagainst 0.9.5's code: PASS.bench/e2e_screen.py: PASS at 120 and 80 columns (the TUI scrollback is the same).bench/ui_check.py: PASS.test/detach-shared-string.test.ts: equal content held once, the 2M-character bound, and a changed file read again.npm run checkis clean../test.sh: coding-agent 337 files pass. The failures are elsewhere and do not involve this change:state-fuzzis a 5 s timeout at load average 130;worker-lifetimepasses when re-run;packages/envneeds the daemon, as before.Not done (data in the notes)
--versiontake 1,142M instructions instead of 93M. Dropping it needs the builtins linked separately in Bun's bundler. That is engine format work, too large for tonight.IntlandTextDecoderbehaviour..bssstored as zeros (1.9 MB) and zero pages in the prebuilt heap (4 MB). These cost disk only (0.7% and 1.5%), compress away, and the heap layout belongs to the start-up work.