本文作者:meng shao(@shao__meng)。版权归作者所有,未经授权禁止转载。


AI 写代码让“写代码”不再是瓶颈,CI(持续集成)成了新瓶颈。Anthropic 的应对是放弃继续打补丁,用 AI 辅助完成了一次架构重写,并得出核心结论:要为指数级增长做设计,因为指数级增长现在真的会来。

Claude 博客:Agentic coding is straining CI. Here’s how we scaled test impact analysis at Anthropic 作者:@edorado93

问题:CI 负载的爆炸式增长

文章开头给出了一组关键数据,描绘了 agentic coding 对工程基础设施的冲击:

  • 工程师每季度产出的代码量约为 2021 至 2025 年间的 8 倍​,其中 约 80% 由 Claude 编写​,Claude 还深度参与 PR 的审查与批准;
  • 测试数量增长 10 倍​,而工程师人数基本没变;
  • 六个月内 CI 任务量增长了 25 倍​。

值得注意的是结构性变化:Claude 倾向于提交更小、更细粒度的 PR​,意味着单位代码会产生更多 CI 任务;agent 在夜间和周末持续工作,抬高了负载的“地板值”。同时,由于人仍然驱动大量 PR,流量依然保持突发特性。基线抬高叠加峰值依旧尖锐,这对容量规划来说是最不友好的形态。

Anthropic 的应对是构建一个测试影响分析(Test Impact Analysis)服务​:放弃对每个 PR 跑全量测试的做法,转而基于历史测试结果和 package 相关性,确定性地选出该跑的测试子集。这个服务由两部分组成:listener(记录每次 CI 运行的测试结果)和 selector(读取历史记录,为新 PR 选择测试)。

v0 的致命缺陷:单进程、单写者

这个服务最初跑在单进程里。原因很经典:维护每个测试的滚动历史,需要一个单写者来顺序应用结果,这天然阻止了水平分片。这个决定在低负载下是合理的,但在 25 倍的负载增长面前迅速崩坏。listener 开始落后于 PR 队列,20 分钟的滞后就意味着数万条测试结果更新未被应用​。

滞后带来的后果远超单纯的“慢”:合并了坏变更会导致所有人的测试变红,引发多起重复排查;flaky 的依赖失败会阻塞合并;新增或修复的测试在 listener 追上来之前根本不会被运行,带来回归风险。

三个补丁,寿命递减。这是全文最有信息量的部分

作者用一年时间打了三个补丁,每个补丁买到的时间都比上一个短得多:

  1. 换更大的机器(10 月)​:把服务的核心数翻倍。所有人都知道这只是权宜之计,最终撑了约 70 天​。
  2. 分片(2 月)​:团队意识到 listener 只需要每个 package 一个写者​,无需全局唯一。Claude 生成了解耦代码,但只撑了 29 天​。
  3. 每日重启(3 月)​:进程每个工作日下午就触及内存上限。团队排查后发现:真正的 bug 只找到四个;换内存分配器毫无作用,说明问题不在 GC;对生产中的单例做内存剖析风险太高;重启买不到一天时间。而重启让服务越掉越远,当滞后超过一小时(发生过数次),大量任务结果直接丢失,selector 只能在陈旧数据上工作。

这个“补丁寿命 70 天、29 天、不足一天”的递减序列,正是指数增长环境下增量式修补的数学必然:负载在指数增长,补丁的容量提升是线性的,两者的差距只会越拉越大。

一个很有时代感的细节:作者在一个内部版 Claude Tag 中维护了一个长期运行的服务监控会话​,当 listener 滞后超过 5 万个任务时,Claude 会主动提醒他,并且能跨月延续上下文。他坦言,Claude 反复主张做彻底重构,但团队每次都选择了再打一个补丁。

重构:把状态移出进程

最终他们接受了 Claude 一直以来的建议。重构思路是标准的分布式系统设计:

  • 引入一个内存数据存储​,把原先单例进程内的状态处理全部卸载出去;
  • 任意 listener worker 都可以处理任意结果并追加到存储中的 journal(日志)​,worker 本身无状态,因此可以水平扩展;
  • 一个独立的小型 consumer 进程每隔几秒将 journal 汇总为每个测试的历史;
  • selector 从存储中快速查询相关历史。

结果是:新架构运行成本更高,但扩展和内存剖析都变得容易​。积压的任务结果事件曲线在切换并调优后转为平坦​。调优工作(journal 大小、worker 数量)大部分由 Claude 自主完成。

最能说明时代变化的一个对比:这次重构一名工程师用了三周​,而一年前类似规模的重构大约需要一个季度。这正是全文论点的闭环:重构变便宜了,所以应该更早、更激进地选择重构,而非补丁。

三条经验教训

  1. 把 AI 的指数级增长计入设计​:假设你的架构将在两个季度内面对 25 倍负载。“过度工程”的门槛正在快速上移,只要预算允许,v0 就可以按感知规模的 10 到 20 倍来设计。
  2. 把可观测性做成 Claude 的眼睛和耳朵​:良好的 instrumentation 让 Claude 能自行 hill-climb、增量式地解决问题,比人工介入快得多。原则是:CI 进多少任务,就要能出多少观测数据。
  3. 从一开始就把状态移出进程​:除非你能度量它并对变更做灰度发布,否则不要把关键服务跑成单实例。

作者预测,随着 agent 驱动的 PR 和测试持续增多,水平扩展的测试选择架构将成为行业标准。