线性工程师 Mufeez Amjad 发布了一份详细报告,介绍了在 AI 编码代理将 CI 变成其最严重的瓶颈后,该公司如何重新设计其持续集成管道——将拉取请求等待时间从六分钟多一点减少到五分钟多一点,而其测试套件自今年年初以来几乎增加了四倍。

这篇文章于 9 月 21 日发布在 Linear 的工程博客上,就像这些事情经常做的那样,以上面的简短说明开始。今年早些时候,Amjad 打开 Linear,发现该公司的 CTO Tuomas 给他分配了一个题为“CI 成本很高”的问题,并要求他在处理该问题时加快 CI 的速度。有关此故事的更多背景信息,请参阅我们正在进行的 人工智能行业报道

当代理超出验证速度时

问题是结构性的,而不是偶然的。 Amjad 写道:“代理已经使代码发布速度呈指数级增长,但验证这些更改的速度却没有完全跟上。”每个拉取请求仍然必须通过 CI,因此随着开发的加速,CI 成为瓶颈——推高基础设施成本,让开发人员及其代理等待反馈的时间更长。

针对两个指标进行线性优化:PR 在 CI 上等待的时间以及消耗的运行时间。经过几个月的工作后的结果:尽管自 1 月份以来测试套件几乎增加了四倍,但拉取请求等待时间从六分钟多一点减少到五分钟多一点,并且每次测试的运行时间大约减少了一半。

这项工作大致分为四类:升级基础设施和工具、优化影响其他工作的作业、减少重复设置以及提高测试执行效率。 Linear 的代码库主要是 TypeScript,但许多优化适用于跨语言和工具链。

更快的机器和本机编译器

一些最早的成果几乎不需要 CI 本身的优化。将工作负载从 GitHub Actions 转移到具有更快的 CPU、更高性能的存储和更好的缓存基础设施的第三方运行程序立即获得了回报:在对切换两侧的两天进行类似比较时,作业的平均运行速度提高了 34%,某些工作负载(例如“tsc”)下降了 52%。

工具链的现代化使胜利更加复杂。切换到原生 TypeScript 编译器“tsgo”后,每周类型检查的中位数减少了 73%——大到足以完全消除类型检查的瓶颈。

没有类型图的 Linting

Linting 是另一个早期目标。 Linear 的一些自定义 ESLint 规则依赖于 TypeScript 类型信息,这迫使每次 lint 运行在评估它们之前构建完整的类型图 - 使得 linting 成为内存最密集的 CI 作业之一。

该团队重写了规则,以在抽象语法树上使用静态分析,识别类似函数的构造和保护模式,而无需任何类型信息。这让 ESLint 完全放弃了 TypeScript,将 API lint 时间减少了 68%,将全存储库 lint 时间减少了 55%,同时内存使用量大幅下降。它还简化了后来向 Oxlint 的迁移,进一步减少了 CI 运行者花在 linting 上的时间。

缩小关键路径

随着个人检查速度的加快,Linear 缩小了范围,将 CI 视为一个系统。这引起了人们对位于其他所有事情前面的小作业的关注 - 在作业级别进行路径更改检测和测试结果缓存检查,这意味着八个 API 测试分片在完成之前都无法启动。

这些修复是细粒度的,但是是附加的。限制获取深度将最慢的门从 94 秒缩短到 20 秒。从不需要工作树的作业中完全删除签出,将时间从 27 秒削减到 7 秒。历史记录有限的稀疏、无 blob 签出又为推送和合并队列事件节省了 11 秒多的时间。总的来说,变更检测作业的中位持续时间从 26 秒下降到 8 秒,p90 从 31 秒下降到 12 秒,最慢运行时间从 138 秒下降到 37 秒。

检查可靠性也需要改进:因为第三方运行程序位于 GitHub 网络之外并依赖于直接 IP 链接,间歇性链接降级有时会导致获取停滞。 Linear 用自己的复合操作替换了“actions/checkout”,该复合操作会通过退避重试,设置“GIT_HTTP_LOW_SPEED_LIMIT”和“GIT_HTTP_LOW_SPEED_TIME”,以便停滞的连接在大约 30 秒后中止而不是挂起,并使用签出缓存将持久的 git 镜像保留在粘性磁盘上。

一个微妙的修复消除了浪费的合并队列时间:缓存标记被写入作为合并之前最终检查的一部分,因此即使在测试通过后,PR 也可以位于队列中。将该写入移动到非门控作业中,可以为每个 API 拉取请求和合并队列条目的合并路径节省 42 秒。总之,这些更改使 API PR 对缓存未命中所需的检查时间缩短了大约一分钟,同时减少了运行程序的启动次数。

每个作业浪费的时间更少

最后一类攻击的设置成本在每个作业中重复出现。每个 API 测试分片在每次运行时都花费 7 到 8 秒的时间使用 apt 安装相同的 Postgres 客户端;将其与 Node 一起移动到小型 CI 基础映像中意味着分片可以开始准备运行。该团队后来发现在安装过程中下载它们有时可能会挂起,然后将本机构建标头添加到图像中。

为什么引起共鸣

这篇帖子触动了开发者的神经:它登上了 Hacker News 的头版,一天之内就获得了大约 250 个点和大约 280 条评论。这种反应很容易解释——Linear 的经验指出了大多数工程组织现在才面临的人工智能辅助开发成本。在几分钟内生成拉取请求的代理仍然等待为人类节奏设计的验证管道,并且等待的每一分钟都会在每个并行工作的代理中成倍增加。

Linear 返工的教训是,瓶颈是可以移动的,但只能通过许多小修复的平淡积累——更快的运行程序、更便宜的类型检查、语法级 lint 规则、上限获取、弹性结帐、预构建图像——而不是任何单一的灵丹妙药。

---

保持人工智能领先地位

获取最新的人工智能新闻、分析和突破——尽在一个地方。

阅读更多人工智能新闻 →