perf(sse): tee re-parses each OpenCode event 4-5x and broadcasts session.activity per token #718

Open
opened 2026-09-25 08:50:05 +02:00 by dries · 0 comments
Owner

Follow-up from the perf report (second tier).

Symptom: `internal/autoapprove/tee.go:237-295`: global envelope unmarshal → `string(global.Payload)` copy → recursive unmarshal → `typeOnly` unmarshal → `parseSessionRef` 1-2 unmarshals; `dispatchTerminalPart` (:297-358) adds 1-2 more on `message.part.updated` with full tool output. `watcher_session_events.go:22-37` then `json.Marshal`s + `broadcastGlobalEvent`s an `ocman.session.activity` event per `message.part.delta`, and `server/broadcast.go:134-152` `coalesceKey` re-unmarshals inside the hub lock when a subscriber is full. Cost is ~5x payload per event on every `/global/event` stream and every per-tab `/api/session/{id}/events` tee (`events.go:18-63`).

Fix: one `json.Unmarshal` into `{Type string; Directory string; Properties json.RawMessage}` and pass the raw properties down; rate-limit `ocman.session.activity` per session (~250 ms). The frontend now ignores same-minute activity (useSidebarSessions), so the server-side limiter is about wire/CPU, not correctness.

Follow-up from the perf report (second tier). **Symptom:** \`internal/autoapprove/tee.go:237-295\`: global envelope unmarshal → \`string(global.Payload)\` copy → recursive unmarshal → \`typeOnly\` unmarshal → \`parseSessionRef\` 1-2 unmarshals; \`dispatchTerminalPart\` (:297-358) adds 1-2 more on \`message.part.updated\` with full tool output. \`watcher_session_events.go:22-37\` then \`json.Marshal\`s + \`broadcastGlobalEvent\`s an \`ocman.session.activity\` event per \`message.part.delta\`, and \`server/broadcast.go:134-152\` \`coalesceKey\` re-unmarshals inside the hub lock when a subscriber is full. Cost is ~5x payload per event on every \`/global/event\` stream *and* every per-tab \`/api/session/{id}/events\` tee (\`events.go:18-63\`). **Fix:** one \`json.Unmarshal\` into \`{Type string; Directory string; Properties json.RawMessage}\` and pass the raw properties down; rate-limit \`ocman.session.activity\` per session (~250 ms). The frontend now ignores same-minute activity (useSidebarSessions), so the server-side limiter is about wire/CPU, not correctness.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dries/ocman#718
No description provided.