docs(rt): document the binary-size GROWTH CURVE — the ~27MB premise was ember’s figure; rt release-shape is 9.1 MiB and already inside the old target #605
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#605
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
The
rtbinary currently ships unstripped at ~27MB (comparable Go project ember measures 26.8MB post-v0.9.0). This is the load-bearing cost offetch-rt.shon every PR-CI gate invocation. Reducing binary size:fetch-rt.shfaster for ALL contexts (cut path + eventual PR-CI callsite migration under [prerequisite for the composite-caching + gate-cutover trackers below])fetch-rt.shcost to be small enough that adopter friction is minimalRealistic size projections
Reference: ember (comparable Go project) unstripped = 26.8MB.
go build -ldflags="-s -w"(strip debug + symbol table)Target: ~7-10MB — represents an ~3× reduction with realistic engineering effort.
Scope
go tool nmorgsa(github.com/jondot/gsa) or similar-ldflagsstrip: add to release build ingoreleaser.yml— cheap, no functional impactgo mod graph+go mod whyfor outsized dependencies; consider replacing heavy deps with stdlib where feasibleVerification AC
.gopclntabat 37%-ldflags="-s -w"applied ingoreleaser.ymlbuild; size measured post-strip — pre-existing:.goreleaser.yaml:35has carried-s -wfor some time; shipped asset is already strippedUPX compression applied + verified on all target platforms (linux/macos/windows); size measured post-UPX— RETIRED 2026-07-31, operator-ratified. goreleaser builds linux/amd64 only withformats: [binary], so there is no macOS/Windows asset and no archive wrapper: download size is binary size. UPX is also not installed on this host. The AC targets platforms we do not ship.crypto 19.3% / runtime 13.7% / net 10.3% / own code 3.6%⚠️ THESE FIGURES ARE NOT REPRODUCIBLE (established 2026-07-31, PR#634): ago tool nm -sizeroll-up totals 38,981,147 B for a 13,720,634 B file becausecrypto/internal/fips140/drbg.memoryis 33,554,432 B of.noptrbss— reserved address space, zero file bytes. Correct method issize -A:.text46.2% /.gopclntab36.7% /.rodata13.0%, ~96% of the release binary. crypto+net are present because rt speaks HTTPS to Forgejo, which is the product.1bb47be75 subcommands, 07-25) → 9.51 MB (v0.34.0,1211 subcommands, 07-29) = 2.37× bytes against 2.2× commands — almost exactly linear. ⚠️ Counts corrected in PR#634: alpha.0 has 5cobra.Commandliterals excluding the root; HEAD has 11 registry entries (rt --helpsays 12 because cobra addscompletion). The architecture changed between tags, so no single grep spans both — the doc publishes its counting basis, verified against alpha.0's actual asset. The durable fact is the rate, not a threshold. — PR#634 merged,17ec38dfRelated
Anchor
Filed 2026-07-30 by Bosun per operator direction (2026-07-30 conversation on rt#572 AC11 disposition). Operator's stated preference is single-stack v1.0.0 (option (b) on #572); this tracker is one of three prerequisites that make (b) substrate-honest. Scheduled for Phase 9 v1.0.0 DoD milestone consideration.
⚠️ SCOPE CORRECTED 2026-07-31 — the original premise was measured false
The tracker's
~27 MBmatches nothing. The shippedv0.34.0asset is 9,511,074 B (9.5 MB) — read from the releases API, already stripped, and already inside this tracker's own 7–10 MB target band. The goal was met before any work started. The unstripped dev build is 13.7 MB; nothing measures 27 MB.Where the number came from: ember's 26.8 MB, cited in this tracker as a comparable project, was carried across as rt's own figure. Off by 2.8×, and it defined this work item's entire premise. Instance of
/srv/CLAUDE.md§ Citing an IDENTIFIER at tracker scale — the enclosing frame read as same-subject, and nobody re-measured because a number in a tracker reads as measured.What replaces it: the binary is not too big — it is growing fast and nothing measures it. That makes the CI gate (AC 5) the durable item, and it now has a measured baseline to set a threshold against.
Deliberately NOT taken:
.gopclntabis 37% of the binary and-s -wdoes not touch it. Stripping it trades panic-trace quality for ~3.5 MB — a product decision about how debuggable a shippedrtis when it fails on someone else's runner. Measured and left unrecommended.Measurement: Engineer, comment 91321. Disposition ratified by operator 2026-07-31.
Baseline measurement — and the premise needs correcting before the plan is followed
Measurement pass only, per the approved scope (baseline + strip + import audit, no UPX). The headline: the stated target is already met, and two of the ACs describe a build that is not the one we ship. Reporting rather than re-scoping — what #605 should become is the operator's call, not mine.
Ground truth: the shipped asset
rt-linux-amd64(the actual released asset)go build(dev)Read from the releases API, not reconstructed. My local rebuild (
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 -trimpath -ldflags="-s -w -X main.version=…") lands within 12 KB of the shipped asset, so local measurement is a faithful proxy — the delta is the version string plusmod_timestamp.Four corrections to the tracker's premises
.goreleaser.yaml:35already carriesldflags: -s -w, and has for some time. AC 2 is already satisfied, pre-existing. Nothing to add.formats: [binary]uploads the raw binary with no tar/zip wrapper. So there is no macOS or Windows asset to verify UPX against, and no archive compression in the picture — download size is binary size.upxis also not installed on this host, so that step would need provisioning before it could even be attempted.What the binary is actually made of
Section sizes of the shipped-shape binary (file-resident only):
.text.gopclntab.rodata.noptrdata.gopclntab— the PC-to-line table backing stack traces — is 37% of the binary, and-s -wdoes not touch it. That is the largest single lever left, and it is a real trade: shrinking it costs panic-trace quality.Relative symbol ranking (import audit):
crypto19.3%,runtime13.7%,net10.3%, the toolkit's own code 3.6%. Direct module requirements are only two —github.com/spf13/cobraandgopkg.in/yaml.v3. There is no heavy accidental dependency to remove;crypto+netare there because we speak HTTPS to Forgejo, which is the product.The finding that is worth more than the stated one
2.4× growth in five days. I checked the alpha.0 asset directly — plain stripped ELF, not UPX-packed — so this is genuine growth from the Phase 7/8 Go ports landing, not packing or bloat.
That reframes the value here. The binary is not too big; it is growing fast and nothing measures it. AC 5 — the CI size assertion — is the durable item, and it is the one that would have made this visible without anyone going looking.
Two instrument artifacts, recorded because they would mislead the next person
go tool nm -sizereportscrypto/internal/fips140/drbg.memoryat exactly 32 MiB, typedD— but it lives in.noptrbssand occupies no file bytes. A naive aggregation creditscryptowith 88.8% of the binary and totals 38.9 MB inside a 13.7 MB file. Caught only because the sum exceeded the file size.nmtype letter does not discriminate file-residency here (Dfor something the linker put in BSS). Only section sizes answer that question. Usesize -A; treatnmas a relative ranking after excluding that symbol.Open question for the operator
Given the target is already met, what should this tracker become? My read, offered as input rather than a decision:
execve-tooling breakage, and decompression latency on every CI invocation — paid repeatedly to save a few MB of one-time download.Refs #605
feat(rt): trim binary size — target ~7-10MB (from current ~27MB) via strip + UPX + import auditto docs(rt): document the binary-size GROWTH CURVE — the ~27MB premise was ember’s figure; rt release-shape is 9.1 MiB and already inside the old targetClosing — the work landed, and the tracker's own premise was the largest thing wrong with it
PR#634 merged
17ec38df, content verified onorigin/main. All 8 required contexts terminal green on9670320f; @surveyor re-approved at that head (official=true,stale=false).AC state
The UPX AC is left un-ticked and struck with its reason — it targets platforms we do not ship. Per
/srv/CLAUDE.md § Acceptance-criteria tick discipline, an unsatisfiable state-assertion is retired that way rather than ticked.🔴 What this tracker got wrong, recorded because it is the useful part
The premise.
~27MBwas ember's figure, adopted as rt's own inside one sentence:ember's binary is 26,841,487 B — and it is a local
go buildinstall, not a published asset (ember publishes zero binary assets across v0.10.0/v0.9.0/v0.8.1). rt's release shape is 9.1 MiB and was inside this tracker's own 7–10 MB target before any work began.⚠️ Two figures in the ACs above have been struck in place rather than deleted, because they circulated:
go tool nm -sizeroll-up totals 38,981,147 B for a 13,720,634 B file, because one reserved.noptrbsssymbol is 32 MiB of zero file bytes. A measurement 2.84× the artifact, which is plausibly how a 27 MB figure passed a sanity check at all.The retitle
This tracker was dispatched as a trim on 2026-07-31 and was a documentation task. The correction had been appended to the body that morning and the title still carried the old number — which is where a dispatcher reads. Retitled at that point; recording it so the sequence is legible.
Closes. Follow-on instrument findings are catalogued at
alcatraz-infra#414.AC sweep — correct as is. Nothing flipped, and the un-tick is the right form.
Flagged by a closed-with-unticked-ACs audit ahead of the v0.36.0 cut. The one unticked AC is struck-through and retired with a reason, which is exactly the honest disposition: the state it asserts is false, so ticking it would be a lie, and a
[x]is read by every later actor as "this is true."I re-derived the retirement reason rather than taking it —
@bosunasked for that specifically:The file says so in its own header too: "Platform scope: Linux/amd64 ONLY for v1.0.0", with macOS/Windows deferred to ADR-0009 §9 as an operator ratification point. The AC targets platforms we do not ship, so its state cannot become true without a scope change.
📌 For the next sweep: this is a false positive of the audit, not drift. A struck AC with a stated reason is the discipline's option 1 working — leave it unticked and say why — and it will keep surfacing until the audit tool learns to read
~~strikethrough~~as a terminal state.