Skip to content

fix(session): giant summary.diffs message starves event loop — ESC abort unresponsive #458

Description

@LeXwDeX

Why

一次 upstream sync 会话把 37.8MB 的全量 git diff 注入 user 消息的 summary.diffsmessage.data = 37,872,527 字节),进程随即进入忙循环:CPU ~142% 持续燃烧、RSS 稳定 9GB、JSC GC 线程(libpas scavenger + heap helpers)满负荷。事件循环被饿死后,ESC 双击的 abort 请求永远得不到调度——SessionPrompt.cancel 第一行日志都打不出来,用户只能 kill -9。此问题此前极难复现,触发条件是单条消息达几十 MB(正常使用到不了的量级)。

证据链(2026-08-28 现场采集)

  • 会话 ses_fe5fb9f843e3IWKjNgbDA0otgN("Sync opencode-official upstream and merge diffs"),run 68f76d00
  • step=4 的 LLM stream 耗时 49.5 分钟(13:22:06 → 14:11:38)才返回,期间进程已在高 CPU
  • step=5 于 14:11:40.573 打出 llm runtime selected(ai-sdk runtime)后:零日志、零事件写入、零 token 产出
  • 进程无任何 TCP 连接(LLM 请求未在网络上),但 CPU/GC 持续燃烧 → 纯 JS 分配循环,非网络等待
  • macOS sample:主线程 ~21% JS 执行 + 其余 kevent,GC 线程满负荷 = 稳态分配风暴(高速分配+回收,RSS 不涨)
  • 注意:会话全部 137 个 parts 仅 695KB —— 发给 LLM 的是小头,37.8MB 集中在 message.data 的 summary.diffs 元数据

根因(已确认)

放大链路:SessionSummary.summarizepackages/opencode/src/session/summary.ts:124-125)把 snapshot.diffFull全量 diff 无上限写入 user 消息 summary.diffssessions.updateMessage 每次都把 37.8MB 的 message.data 写入 message 行,并以 message.updated 事件形式再写一份进 event 表 + SSE 广播(实测 event 表单条 message.updated37.87MB;全局 opencode.db 已被撑到 10GB)→ 同进程 TUI 接收并处理巨型事件 → 序列化/渲染路径分配风暴 → GC 满负荷 → 事件循环饿死 → abort HTTP 请求死在队列里(ESC 双击无效的直接机理)。13:21:19 的"成功 cancel"实为用户强退进程时走的清理路径。

修复方案(交付分支 feat/458-giant-summary-guard,PR #459

三层防御,diffs 是纯元数据(TUI 展示用),截断不影响发给 LLM 的内容:

  1. 源头截断 summary.tssummarize 写回前按总预算(256KB)截断文件列表
  2. 读护栏 session.ts 读路径:DB 读出超限 summary_diffs 即剥离(保留 additions/deletions/files 统计)——存量治愈:已存在的 37.8MB 消息重新加载时被卸载,旧会话可安全继续
  3. 写护栏 session.ts 写路径:toRow 写库前同样截断,保证任何路径写入 DB 的 summary_diffs 不超预算

后续拆分项(不在本 PR):abort 路径对事件循环饿死的韧性(cancel 不应依赖被饿死的 loop)、事件循环 lag watchdog。

环境

  • opencode 1.0.34,macOS,provider=local-proxy-compatible/glm-5.3-flash(ai-sdk runtime)
  • 现场证据:sample 输出已存 /var/folders/jm/w5g1j5td4vl8164rqwl96fn80000gn/T/opencode/stuck-sample.txt(临时目录,如需保留请及时转存)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-triageMaintainer needs to evaluate this issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions