You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf: OpenCode native binary startup must beat the bun binary — attribute and remove the module-init cost (measured 13× bun CPU on the Aug 21 build) #10106
Measured 2026-09-12 (dev Mac, load avg ~100 — wall inflated; CPU is the fair number)
binary
--version wall
user CPU
max RSS
official bun-compiled opencode 1.17.7
1.0–1.5 s
0.54 s
185 MB
bun run src/index.ts --version (transpiles on the fly)
2.8 s
0.85 s
—
perry Aug-21 binary (minimal profile, 2,454 modules, 213 MB, perry 0.5.1512)
15–29 s
6.8–7.0 s
563 MB
same, --help
14.8 s
7.0 s
—
A sample of the stripped binary shows the main thread 100 % in generated code (no wait states), i.e. eager module initialization of the graph (Effect's 225 modules build Schema/Layer/Context objects at import; drizzle tables; yargs command tree). No startup number exists for the full graph (4,063 modules on v1.18.30; 7,136 on the Windows full build #9133), so expect worse before optimization.
Target
On the quiet Mac mini (perry@perry-macos.local), same host, five warm runs each, paired A/B per PERRY_STARTUP_PLAN S1 discipline:
opencode --version: user CPU ≤ 0.5 s, wall ≤ 1.0 s, RSS ≤ 185 MB (beat the official v1.18.30 binary from gh release download v1.18.30 -R anomalyco/opencode -p 'opencode-darwin-arm64.zip').
opencode --help and TUI time-to-first-frame: below bun.
Scope
Attribute: symbols build (strip=none, PERRY_MAIN_STACK_MB if needed), sample/Instruments over --version, plus PERRY_DEBUG_INIT module-init trace; produce a per-module init-cost table (top 50) and a per-runtime-helper table (class registration, closure allocation, object-literal construction, string interning, regex compile — regex construction is eager and SipHash-keyed per pattern in perry, see the regex analysis note in secret-tests memory, GC minors during init).
Lazy work: anything perry does per module that bun does not (e.g. eager class/shape registration, module-global slot promotion, side-table setup) becomes lazy or batched; check the young-gen / tenuring configuration during init (563 MB RSS vs 185 MB suggests allocation volume, not just code size).
Graph-level: confirm the compiled graph does not initialize modules bun would never evaluate (dynamic-import-only subgraphs such as Code Mode/typescript, prettier, @babel/* via the runtime Solid plugin — must not be in the eager init order; fix(compile): support full OpenCode source builds #9133 kept dynamic imports out of eager init, verify on this graph).
Binary size / page-in: 213 MB → the first-run variance (16→29 s) hints at page-in; measure cold vs warm and consider PERRY_LL_SIZE_OPT=1 + optnone threshold (perf(compile): reduce generated bundle bloat #8418) trade-offs.
Re-measure after each lever with the A/B script; keep raw samples in secret-tests/opencode-1.18.30-inventory/perf/.
Acceptance
Attribution report with the top-50 module-init costs and the runtime-helper breakdown, on the full v1.18.30 graph.
--version user CPU and RSS below the official bun binary on the Mac mini, two independent batches.
TUI first frame not slower than bun.
No correctness regressions: the 22 node startup oracles (PERRY_STARTUP_PLAN) and the cc --help parity gate stay green.
Parent: #10107. Related: PERRY_STARTUP_PLAN.md (PR #10066 tiny-path work), #6532/#6533/#6534 (cc
--version227 ms), #9441 (idle tail), scavenge/tenuring notes.Measured 2026-09-12 (dev Mac, load avg ~100 — wall inflated; CPU is the fair number)
--versionwallbun run src/index.ts --version(transpiles on the fly)--helpsampleof the stripped binary shows the main thread 100 % in generated code (no wait states), i.e. eager module initialization of the graph (Effect's 225 modules buildSchema/Layer/Contextobjects at import; drizzle tables; yargs command tree). No startup number exists for the full graph (4,063 modules on v1.18.30; 7,136 on the Windows full build #9133), so expect worse before optimization.Target
On the quiet Mac mini (
perry@perry-macos.local), same host, five warm runs each, paired A/B per PERRY_STARTUP_PLAN S1 discipline:opencode --version: user CPU ≤ 0.5 s, wall ≤ 1.0 s, RSS ≤ 185 MB (beat the official v1.18.30 binary fromgh release download v1.18.30 -R anomalyco/opencode -p 'opencode-darwin-arm64.zip').opencode --helpand TUI time-to-first-frame: below bun.Scope
strip=none,PERRY_MAIN_STACK_MBif needed),sample/Instruments over--version, plusPERRY_DEBUG_INITmodule-init trace; produce a per-module init-cost table (top 50) and a per-runtime-helper table (class registration, closure allocation, object-literal construction, string interning, regex compile — regex construction is eager and SipHash-keyed per pattern in perry, see the regex analysis note in secret-tests memory, GC minors during init).@babel/*via the runtime Solid plugin — must not be in the eager init order; fix(compile): support full OpenCode source builds #9133 kept dynamic imports out of eager init, verify on this graph).PERRY_LL_SIZE_OPT=1+ optnone threshold (perf(compile): reduce generated bundle bloat #8418) trade-offs.secret-tests/opencode-1.18.30-inventory/perf/.Acceptance
--versionuser CPU and RSS below the official bun binary on the Mac mini, two independent batches.--helpparity gate stay green.