ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

复盘:一个对话把编辑器跑内存溢出了

复盘:一个对话把编辑器跑内存溢出了

现象

环境:Pink
大模型:Deepseek
一直在同一个对话里干活,跑着跑着编辑器就卡死。reopen 之后重新加载那个对话,再跑一次又死。点 delete 想删掉它 —— 也死。最后只能强杀进程。

图 1:reason: ‘oom’ —— 内存耗尽,不是普通报错

三个人会误判的方向:- 以为是对话太长、轮数太多 → 其实文件里只有 190 条记录。

  • 以为是内存泄漏、进程没释放 → 其实新开窗口内存立刻正常。
  • 以为是 delete 按钮有 bug → 其实 delete 也需要先把它读进内存。

reopen 之后,那个卡死的对话依然停在 SESSIONS 列表最上面,点开就再崩一次:

图 2:问题会话一直在 SESSIONS 里,点进去就是重跑崩溃
想删掉它,右键里的 Delete 同样卡死:


图 3:Delete 也得先加载会话内容,所以一样会死

真正的原因:一条记录 212 MB

那个会话文件(.jsonl)里,有一条记录单独占了 212 MB,整个文件 222 MB。

来源很具体:一次浏览器页面调试,脚本把整张图集纹理的逐像素数组原样返回了 ——{"0":0,"1":0,"2":0,...}一共 220 万项,变成 169 MB 的 JSON 字符串,再被写进会话文件。

正常会话是 0.1~2 MB。这一条顶别人两百个。

三个现象的对应关系:

现象解释
跑着跑着就死那条记录被写进文件的瞬间,内存直接被撑爆
reopen 又死记录永久留在文件里,打开会话就要整体反序列化 + 渲染
delete 也死删除前同样要先把它加载出来

关键点:会话文件是"打开即全量载入"的。文件多大,打开时就要吃多大的内存。所以一旦某条记录过大,这个会话就永久变成了一个打开即死的雷。

怎么解决的

  1. 先定位:按体积排序所有会话文件,一眼就看出两个异常(274 MB 和 222 MB)。
  2. 再隔离:把超大会话整体移动到备份目录,而不是删除 —— 文件不在原位,PinK 就不会再加载它,原内容也没丢。
  3. 最后复查:剩下全部会话合计只有 3 MB。


图 4:按体积排序直接看到两条异常,备份后移除而非删除
整个过程不需要重启,也不需要手工去点那个卡死的标签页。

怎么防

单靠"下次注意"没有用,得做成不需要记的机制:

第一层 · 自动约束

仓库根放一个AGENTS.md,每次新对话自动加载,写死一条:工具返回只给聚合数字(计数/尺寸/fps/hash),禁止逐像素数组、base64、整页 DOM、大段 JSON;单次返回体 ≤ 100 KB,超了就写临时文件再分段读;截图只给路径。

第二层 · 主动开局

/安全开局命令:开工前先读项目契约,再带上这套返回上限约束。

第三层 · 定期巡检

tools/pink-session-guard.ps1扫描会话体积,超过阈值自动归档:

  • -Report只查看
  • -WhatIf预演不动文件
  • -ThresholdMB 20真正归档
  • -InstallTask装成计划任务,每 20 分钟自动跑

给别人的三条硬经验

  1. 看会话文件体积,别看对话轮数。正常 0.1~2 MB,超过 20 MB 就该警觉。
  2. 调试脚本的返回值必须自己收口。页面里return JSON.stringify({几个数字}),永远不要把原始缓冲、像素、快照搬回上下文。
  3. 崩溃的会话可以用"移走文件"救回来。备份目录是%APPDATA%\PinK\User\chat-backup\,挪回workspaceStorage\<id>\对应子目录即可还原。

代价

AGENTS.md常驻约 500~700 tokens。一次正常任务 5 万~20 万 tokens,占比不到 1%。换取的是不再有打开即死的会话 —— 很划算。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进