跳转至

一年吃掉一块固态硬盘,Codex日志bug被骂「劣质软件

Ch09.112 一年吃掉一块固态硬盘,Codex日志bug被骂「劣质软件

📊 Level ⭐⭐ | 8.1KB | entities/一年吃掉一块固态硬盘codex日志bug被骂劣质软件.md

一年吃掉一块固态硬盘,Codex日志bug被骂「劣质软件

OpenAI Codex(编程 Agent)的 SQLite 反馈日志 (logs_2.sqlite) 存在严重的写入放大问题。默认的 Level::TRACE 配置导致每 15 秒进行约 36,000 次数据库插入加删除操作,一年产生约 640TB 的硬盘写入量,足以耗干一块消费级固态硬盘的寿命。

技术细节

  • 写入模式:Codex 使用 SQLite WAL 模式,每 15 秒执行约 36,211 行 INSERT,同时删除等量旧行,始终保持数据库约 1.2GB 大小。这种 insert-and-prune 机制虽然表面文件大小不变,但每次写入都对存储介质产生实际磨损。
  • 数据规模:自增 ID 已超过 55 亿,但留存行仅约 50 万行(写入/留存比约 1 万倍)。主要写入来源是文件系统 inotify 事件(ld.so.cache 被记录 12.8 万次、locale.alias 3.8 万次等调试日志)。
  • 根因:SQLite 反馈日志 sink 初始化的 RUST_LOG=TRACE 默认配置,将每个 WebSocket 数据包完整记录到日志中。
  • 影响:连续开机 21 天产生 37TB 写入,年化 640TB,超过消费级 SSD 150-600 TBW 的标称寿命。文件占用量小(~1.2GB),故障极其隐蔽,只能通过读取 SSD SMART 健康计数发现。
  • 隐蔽性:日志库始终只有 1.2GB 大小,表面无异常;但自增行 ID 冲到 55 亿,真正留存的行仅 50 万。硬盘损耗只计写入量,不计当前文件大小——55 亿行全都落过盘,删掉也退不回已经付出的写入。

修复状态

Anthropic 在收到报告后进行了修复,削减了约 85% 的日志写入量。但用户无法自行修改(Codex 桌面端闭源)。该问题在 Hacker News 上被评论为典型的劣质软件(slopware)。

深度分析

隐蔽性工程漏洞:资源无预算制度的设计之殇

这个问题最值得深思的不是技术细节,而是它为什么能潜伏这么久。代码层面,根源是 with_default(Level::TRACE) 将日志级别硬编码为 TRACE,且用户通过 RUST_LOG 环境变量无法覆盖——"你配置了,它假装没听见"。但从工程管理角度看,这表明 Codex 的日志和遥测系统从一开始就没有"资源预算"概念。工程团队没有为常驻进程设置磁盘写入预算(budget per resource),这类问题在传统的移动端开发中很早就通过"电量预算""网络预算"等约束机制被系统性地防范。Agent 常驻用户机器这一新场景,需要建立类似的资源预算制度。

系统性问题堆积而非单一Bug

这不是孤立事件。报告者发现 Codex 仓库中至少还有 8 个类似的"日志无界增长"Issue:#17320(WAL狂写)、#24275(logs_2.sqlite疯涨)、#22444(WAL无限增长)、#26374(一天写0.75GB)、#27911(4KB数据库写成11MB/s)、#20563(进程空闲狂写盘)、#27020(Windows磁盘活跃100%),最早可追溯到#12969(引入 TRACE 级别的 PR)。这些 Issue 的根因高度一致——同一套遥测体系的设计缺陷。表明问题的本质不是某个粗心开发者的失误,而是组织层面的质量流程缺失。

"硬件性能兜底"掩盖软件质量退化

一条高赞评论切中要害:"放十年前,日志开到 TRACE,程序当场卡死,当天就被修掉;如今 CPU 够快、内存够大、磁盘够猛,这点毛病被硬件性能悄悄消化。"这一观察揭示了 AI 时代软件工程的一个系统性风险——硬件性能的快速提升正在消解软件的资源约束意识,使得资源泄漏类 bug 从"程序崩溃"退化为"缓慢死亡",从"显性故障"退化为"隐性磨损"。Agent 作为 7×24 小时常驻进程,其资源消耗的累积效应远超传统工具。

编程Agent的竞争已从模型能力蔓延到工程质量

这个问题在 Hacker News 上引发了对 AI 编程工具整个品类质量标准的讨论。开发者们对比 Claude Code 也往本地猛写调试日志(有人将日志目录软链到 tmpfs 给 SSD 续命),指出两家旗舰犯的是同一类毛病。当模型能力的差异逐渐缩小(Claude Code vs Codex 在编码基准上的差距从倍数缩小到百分比),工程质量——资源管理、稳定性、可观测性——正在成为开发者选择 Agent 工具的差异化因素。

修复比例而非根治的工程文化

Anthropic 的三个修复 PR 合计削减约 85% 写入。但从年化 640TB 降到 96TB(6年烧穿一块 SSD),本质上只是将问题从"紧急"降级为"不那么紧急",而非根治。两个现象值得注意:(1) 第三个 PR 需要等下一个版本才上线——修复本身是分段的;(2) 没有任何 PR 涉及治理层面的流程改进(如何防止同类问题再次发生)。这反映了当前 AI 公司的工程文化倾向:快速响应外部可见故障,但系统性改进(资源预算制度、代码审查中的非功能性需求检查)的优先级较低。

实践启示

  1. 为常驻 Agent 设置资源预算:7×24 小时运行的 Agent 应有明确的磁盘写入预算(MB/天)、内存预算和 CPU 预算。并将这些预算纳入 CI/CD 门禁,超过阈值标记为 bug。对于需要长期运行的生产 Agent,这是必须建立的质量基线。

  2. 配置不可被硬编码覆盖with_default(Level::TRACE) 且无视 RUST_LOG 环境变量的设计是反模式。所有可配置参数应遵循"用户配置 > 厂商默认值 > 代码硬编码"的优先级链,并允许用户在不修改代码的情况下覆盖任何默认行为。

  3. 资源泄漏检测使用物理指标而非逻辑指标:本例中文件大小(1.2GB)完全正常,但 SSD SMART 健康计数暴露了 37TB/21天的实际写入。Agent 的可观测性方案应包含物理资源指标(磁盘实际写入量、实际内存分配峰值),而不仅仅是应用层指标(日志文件大小、进程内存 RSS)。

  4. Agent 质量评估需包括非功能性指标:模型能力(编码准确率、任务完成率)不应是选择 Agent 的唯一标准。资源消耗曲线、长期运行的稳定性、升级后的回归风险,这些非功能性指标对生产级使用同样关键。

  5. 快速修复不等于系统性改进:削减 85% 写入是应急响应,但不是系统性解决方案。建立防止同类缺陷再次出现的机制(如 CI 中的日志写入量基线检查、代码审查中的资源预算 checklist)比单次修复更有长期价值。

相关实体

原文存档