Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
- Run
vp run devonmain(48a2923) with a fresh home dir, pair the browser, and leave the web app idle on a thread. Or leave the 0.1.3 desktop app idle. - Watch DevTools Network for
POST /api/observability/v1/traces, or tailuserdata/logs/server.trace.ndjsonforEnvironmentRegistry.reconcilePlatform.
Expected behavior
When the environment topology hasn't changed, an idle client doesn't export traces apart from the periodic web.backgroundActivity.report.
Actual behavior
The web platform connection source polls topology every 3 seconds (PLATFORM_POLL_INTERVAL in apps/web/src/connection/platform.ts). layer.ts passes every result to EnvironmentRegistry.reconcilePlatform, even when the poll returns the same cached registrations. Each no-op run starts four spans: reconcilePlatform → installPlatformRegistration → withLeaseLock → installEntryLocked. These are parented under the long-lived clientRuntime.connection.application.start span. As a result, an idle client exports a trace about every 3 seconds, and the server appends it to server.trace.ndjson.
Measured on main, idle for 60 s, with a probe counting fetches and the OTLP span names they carry:
| trace POSTs | reconcilePlatform chains |
|
|---|---|---|
| Web (Chrome, visible and focused) | 22 | 15-20 |
| Desktop dev app (Electron, window hidden) | 16 | 15 |
In the server trace file, with a thread open and nothing happening, spans rooted in this reconcile were 160 of 912 spans and 178 KB of 550 KB written per 2 minutes. That makes them the largest idle source by bytes, so they also rotate useful traces out of the 10 MB trace log sooner. v0.1.2 behaves the same way.
The repeated reconcile also acts as a retry. When a best-effort write fails, the next identical poll runs it again. Those writes are clearing PR routing permission, storing a platform bearer, and removing a shadowed persisted registration. The registry.test.ts case "retains a healthy runtime when the platform repeats an identical registration" covers this. So simply deduplicating the stream isn't a safe fix.
Proposed fix (I have a branch ready, with a test that fails on main):
- The registry remembers the last registrations that applied fully.
- It skips an identical repeat without starting a span.
- Those best-effort writes report failure, so a failed write still gets retried on the next poll.
With it, the same web run drops to 3 trace POSTs in 78 s, all of them the activity report, and 0 reconcile spans.
Related:
- [Bug]: Windows desktop typing lags even in empty chats; browser interface is smooth #12689 is about the same 3 s poll. Its renderer profile shows
getLocalEnvironmentBootstrapssync IPC inside the poll. This issue doesn't touch the poll itself or its IPC. - [Bug]: Desktop server private memory climbs ~25-30 MB/h while idle (immortal Effect parent spans + always-on tracing) #5410 is a similar concern on the server side: idle no-op polls retaining tracing state.
Impact
Minor bug or occasional failure
Version or commit
main @ 48a2923; also reproduced on v0.1.2
Environment
macOS on Apple Silicon: vp run dev with Chrome, and the Electron dev app. I first noticed it in the Linux desktop app running in a QEMU VM, where every idle wakeup costs host battery.
Logs or stack traces
# server.trace.ndjson, last 120 s idle on main, spans grouped by root (count, bytes)
240 120598 Scheduler.register
221 88058 VcsStatusBroadcaster.retainRemotePoller
160 177840 clientRuntime.connection.application.start # the client's 3 s reconcile
83 36621 ProviderInstanceRegistry.makeProviderInstanceRegistry
45 50192 web.backgroundActivity.reportWorkaround
None.
Activity
sscarduzio commentedon Oct 28, 2026
I re-measured this on a production build, since the numbers above came from short dev-mode samples.
Setup:
t3 servebuild (vp pack). The server code is identical between the two variants; only the web bundle differs: A =main48a2923, B = the proposed fix.proc_pid_rusageover the server process tree and the whole Chrome process tree.Per minute, mean of 2 runs per variant:
mainreconcilePlatformspansIn absolute terms the saving is small: about 0.4% of one core across server and browser. Relative to the rest of the idle work it's large, though: about a third of idle client CPU, a quarter of idle server CPU, and 43% of idle server disk writes (~450 MB/day). The A and B runs don't overlap.
Not covered: