Conversation
The entrypoint statically imported every command module (server, session, sdk, config schemas) at process start, costing tens of seconds and ~200MB RSS even for fast paths like --version. Register commands through a delegating module that only loads the real implementation when yargs parses an invocation that exercises it. Measured: --version instructions 10.4B -> 5.6B (-46%), peak RSS 224MB -> 132MB (-41%), user CPU 3.4s -> 1.9s (-44%). Also decouple UI.cancelled-error from the effect import so the ui module loads without pulling in the full effect runtime.
…mode updateMessage/updatePart published full snapshot events to the durable event table on every change, duplicating the complete payload per update. A single 23MB message re-rendered 90x wrote ~2GB of redundant JSON to the event log (the user's opencode.db grew to 7GB, 6.4GB of it the event table). The only consumer of these durable rows is the experimental workspaces sync (off by default); the local UI/SSE/projection read the projected message/part tables. Add PublishOptions.persist (default true = unchanged). updateMessage/ updatePart pass persist: experimentalWorkspaces so local installs stop appending to the event log while still projecting and notifying. With workspaces enabled the behavior is byte-identical to before. The bridge only emits sync envelopes for events carrying a durable marker, so local events are never observed by cross-instance sync. Measured: write-path E2E (90x growing part up to 24MB) 10.2s -> 5.5s (-46%); publish micro-bench -92%; durable bytes per turn 100% eliminated. Add db compact command as an optional one-shot tool to reclaim rows already written (guarded against experimentalWorkspaces, which requires contiguous seq for sync replay).
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Based on my search results, I found two potentially related PRs (excluding the current PR #47661): Related PRs:
These are not exact duplicates but address related concerns about event storage optimization and database maintenance. |
The publish timing bench was flaky under machine load and duplicated the behavioral coverage already provided by event-persist-gate. The measured speedup (write-path E2E -46%, publish micro-bench -92%) is captured in the perf commit message instead of as a timing assertion.
…tract Reviewers need the invariant spelled out: the local-only publish path supplies an inert seq placeholder to projectors (none read it) and skips commit hooks by design (no caller combines them). Adds the rationale for gating message/part persistence on experimentalWorkspaces in session.ts.
What
Two performance fixes for local single-machine usage, no capability removed.
1. Lazy-load CLI commands (
refactor(opencode))The CLI entrypoint statically imported every command module (server, session, sdk, config schemas) at process start — tens of seconds and ~224MB RSS even for
--version. Commands now register through a delegating module (cli/lazy-command.ts) that loads the real implementation only when invoked. Also decoupledcli/uifrom theeffectimport.--version, same commit, fresh worktree2. Stop writing duplicate snapshot events in local mode (
perf(core))updateMessage/updatePartpublished full snapshot events to the durable event table on every change — a single 23MB message re-rendered 90x wrote ~2GB of redundant JSON to the event log (user DB grew to 7GB, 6.4GB of it the event table). The only consumer of those durable rows is the experimental workspaces sync (off by default); local UI/SSE/projection read the projected tables.Adds
PublishOptions.persist(defaulttrue= unchanged).updateMessage/updatePartpasspersist: experimentalWorkspacesso local installs stop appending to the event log while still projecting tables and notifying SSE. With workspaces enabled, behavior is byte-identical; the bridge only emits sync envelopes for events carrying a durable marker.Combine with an optional
db compactone-shot to reclaim rows already written (guarded againstexperimentalWorkspaces, which requires contiguous seq for sync replay).Why
Tests
event44,event-persist-gate2,event-compact2 — 48 passsession8,persist-gate2 (OFF+ON),cli/error6 — 16 passhttpapi-event(SSE) — 3 passfull prompt loop(prompt.test) — projects tables, 0 durable rowsENOEXEC(broken env); CI runs the full workspace check.Reviewer notes
persist:falsebranch passes projectors a placeholderdurable.seq = -1; no current projector reads seq (they upsert by entity id). Documented incore/event.ts.persist:falseskips thecommithook by design; no caller combines them.db compactgaps (needs design before re-enabling with workspaces).