Agentic coding 让 CI 承压
来自 Claude Blog · 期号 2026-09-14
摘要
Anthropic 工程师人均每季度代码产出是 2021-2025 年的 8 倍,其中 80% 由 Claude 编写。代码生成不再是瓶颈,CI 开始承压:六个月里 CI 任务量增长了 25 倍。 Anthropic 用确定性测试影响分析服务来决定每次变更跑哪些测试。该服务依赖一个单例进程:监听器记录每次 CI 运行的结果,选择器根据历史决定 PR 跑哪些测试。当每秒有多个 CI 任务时,监听器开始落后于 PR 队列。 团队打了三个补丁:先给单例加倍核心数(撑了 70 天),再按包分片(撑了 29 天),最后每天重启(撑了不到一天)。每次修复的寿命都在缩短。 最终方案是给服务加上内存数据存储,把状态从进程中移出去。现在任何监听器 worker 都可以处理任何结果,写入日志后立即释放内存——无状态,可水平扩展。一个单独的消费者进程每隔几秒把日志汇总成每个测试的历史。整个重构由一个工程师在三周内完成。 作者给工程团队的建议:假设你的架构在两个季度内会承受 25 倍负载;从一开始就把状态移出进程;为你的服务做好监控,让 Claude 能自主发现并修复问题。 原文是 Anthropic 工程师 Sachin Malhotra 的工程复盘,附了完整的架构演进时间线。
深读
导读 Anthropic 的工程师在 AI 辅助下人均季度代码产出是此前的 8 倍,80% 的代码由 Claude 编写。当代码生成不再是瓶颈,CI 系统开始承压:六个月里 CI 任务量增长了 25 倍。这篇文章详细记录了团队如何通过三次临时修补和一次彻底重构,将测试影响分析服务从单例瓶颈改造成可水平扩展的架构,核心教训是:永远要为指数级增长做规划。 关键信息 - Anthropic 工程师人均每季度代码产出是 2021-2025 年的 8 倍,其中 80% 由 Claude 编写。 - 六个月里 CI 任务量增长了 25 倍,同时代码库的测试量增长了 10 倍。 - 三次临时修补的寿命依次递减:加倍核心数撑了 70 天,按包分片撑了 29 天,每日重启撑了不到一天。 - 最终方案是为服务加上内存数据存储,将状态从进程中移出,使监听器 worker 变为无状态、可水平扩展。整个重构由一个工程师在三周内完成。 逐节讲解 问题背景:AI 加速代码生成,CI 成为新瓶颈 Anthropic 工程师在 AI 辅助下人均季度代码产出是此前的 8 倍,Claude 不仅编写了其中 80% 的代码,还参与 PR 审查和批准。代码生成不再是瓶颈,CI 开始承压。同时代码库的测试量增长了 10 倍,工程师人数仅小幅增加。这导致六个月里 CI 任务量增长了 25 倍。 原始架构:单例的测试影响分析服务 Anthropic 构建了一个确定性测试影响分析(test impact analysis)服务,它根据历史表现和包相关性决定每次变更跑哪些测试。该服务依赖两个组件保持同步:一个“监听器”(listener)记录每次 CI 运行的结果,一个“选择器”(selector)根据历史决定 PR 跑哪些测试。由于需要为每个测试维护运行历史,整个服务以单进程运行,无法水平分片。当每秒有多个 CI 任务时,监听器开始落后于 PR 队列。20 分钟的监听器延迟可能导致数万个测试更新未被应用到选择器,进而引发一系列问题:坏变更被合并后测试开始大面积失败、依赖出现 flaky 后阻塞合并、新测试或修复的测试无法及时运行。 三次临时修补:寿命越来越短 第一次修补是给单例加倍核心数,撑了 70 天。第二次修补是按包分片:监听器不需要单个 writer 来正确排序测试结果,只需要每个包有一个 writer。Claude 生成了将每个包的状态拆分为独立 worker 的代码。这次修补只撑了 29 天。第三次修补是每日重启:到 3 月,进程在大多数工作日的下午就达到内存上限。团队尝试了找 bug、换内存分配器等快速手段均无效,最终发现每日重启只能撑不到一天,而且服务会逐渐进一步落后。 最终方案:无状态、可水平扩展的架构 团队给测试选择服务加上了内存数据存储(in-memory data store),将原本…