轻舟智航 · 研发效率基础设施

Buildfarm · 高速分布式编译与测试

深度优化 Buildfarm 分布式构建平台,承担上千节点的日常保障与集群开发优化,以远端并行执行和构建缓存复用,加速 C++、Go、JavaScript 与 Rust 研发反馈。

← 返回工作经历 · 构建架构 · 测试分片设计

工程规模与项目价值

千节点计算资源池

上千节点日常保障与集群开发优化,约 20,000 核 CPU、40 TB 内存、300 TB 存储,为高并发编译与测试提供共享基础设施。

95%+ 构建缓存命中

复用已完成 Action 的构建结果,减少重复编译;将必须执行的任务并行分配到集群,缩短多语言项目的构建与测试等待。

工作的核心是把高速构建转化为可持续的工程能力:维护大规模 Worker 资源池,围绕执行并发、输入准备、缓存与集群稳定性持续优化,让开发者和 CI 共享构建成果。

架构:缓存优先,未命中任务进入远端执行

Buildfarm 远端缓存与分布式执行架构Bazel 客户端先查 Action Cache,命中后按结果摘要读取 CAS;未命中时上传缺失输入并提交 Execute。Buildfarm Server 协调操作队列,Redis Backplane 保存共享状态。Worker 匹配平台、拉取输入、执行进程、回报结果,输出写入 CAS,可缓存结果写回 Action Cache。 按摘要上传输入 / 读取输出CAS → 输入拉取 输出摘要引用 开发机 / CI · Bazel依赖图 → Action / 输入摘要上传缺失输入到 CAS Action Cache · ACAction digest → ActionResult命中后获取输出摘要 内容寻址存储 · CAS输入树 / 文件 / 输出 / 日志按内容摘要读取与复用 Buildfarm Server · REAPIExecute / 状态流 · 校验与排队处理协调 Ready-to-Run 队列 Redis Backplane · 共享状态操作队列 / Worker 注册 / 状态通知AC 记录 / CAS 所在分片索引 ① Match取队列任务匹配平台与资源 ② Input FetchCAS → 本地缓存准备隔离执行目录 ③ Execute编译 / 链接 / 测试并发与超时约束 ④ Report Result输出上传 CAS完成状态返回客户端 01 客户端与缓存接口02 调度协调与共享状态03 Worker 资源池 · 每个 Worker 的执行流水线AC 未命中 → Execute可缓存结果写回 AC阶段间背压控制 CPU、I/O 与网络占用
按 Buildfarm 官方 Shard 架构归纳的逻辑图。AC 与 CAS 为服务职责,AC 数据及 CAS 位置索引由 Backplane 管理,CAS 内容由存储分片承载;图中不代表它们必须独立部署。个人集群规模与命中率来自项目实践。
  1. 先复用结果:Bazel 根据输入树、命令与环境等构造 Action 摘要;命中 AC 后取得 ActionResult,再从 CAS 获取需要的输出,跳过重复执行。
  2. 再调度执行:缓存未命中时,补齐 CAS 中缺失的输入并提交 Execute。Server 处理操作并组织执行队列,Worker 按平台条件获取匹配任务。
  3. 输出进入下一轮复用:Worker 拉取输入、运行编译或测试,上传输出;符合缓存条件的结果写入 AC,供后续构建复用。执行状态经服务端返回客户端。

源码参考:Codex 的确定性测试分片

Codex 开源仓库的 Windows Bazel CI 使用四个并行作业,将测试目标标签进行校验和取模,稳定分配到各分片。该逻辑发生在 CI 选择测试目标时;远端执行器随后再决定每个 Action 由哪个 Worker 执行。

Codex Windows Bazel CI 测试目标哈希分片查询测试目标并排除 V8 与 manual 目标,按 C locale 排序。对每个目标标签加换行后执行 cksum,取输出第一列,对四取模再加一,得到一到四的 shard。每个 CI 作业只运行自己的目标集合,最后汇总四个作业结果。 Bazel query → 目标标签排除 V8 / manual 测试LC_ALL=C sort label + LF → cksumPOSIX CRC 校验和取输出第一列整数 bucket = (checksum % 4) + 1相同标签、相同分片数得到确定的分片编号 CI shard 1bazel test · bucket = 1缓存查询 / 构建 / 测试 CI shard 2bazel test · bucket = 2缓存查询 / 构建 / 测试 CI shard 3bazel test · bucket = 3缓存查询 / 构建 / 测试 CI shard 4bazel test · bucket = 4缓存查询 / 构建 / 测试 汇总四个 CI 作业结果检查所有分片是否成功 → 汇总通过 / 失败
对应公开源码 .github/workflows/bazel.yml。这里的哈希用于测试目标分组,不是 CAS 分片寻址,也不是将任务固定绑定到某台 Worker。

稳定且无需中心状态:每个 CI 作业可以独立算出同一目标的归属,新增目标不会使其他目标因列表顺序而整体迁移;改变分片总数则会重新映射。哈希均分目标不等于执行时间均衡,长耗时目标仍可能决定整轮完成时间。

目标内部:以 FNV-1a 对测试用例再次分片

配置有效分片参数且未传额外 libtest 参数时,启动器列出 Rust libtest 用例、排序并排除跳过项,对测试名的字节序列计算 32 位 FNV-1a,再对分片总数取模。当前进程仅运行与自身零起始分片编号相符的用例,并使用 --exact 精确选择。额外 libtest 参数会直接交给测试程序,保留调用者的过滤行为;未配置分片时执行全量用例,若配置跳过项则仍应用对应过滤。

Codex Rust 测试用例 FNV-1a 哈希分片列举测试名并过滤后,初始化哈希2166136261,对每个字节先异或,再乘16777619并保留低32位。哈希对TOTAL_SHARDS取模,等于当前SHARD_INDEX的用例通过exact运行。 libtest --list排序 · 跳过过滤测试名 → 字节序列FNV-1a 32-bit · 初值 2166136261逐字节:h = ((h XOR byte) × 16777619) & 0xffffffffh % TOTAL_SHARDS是否等于 SHARD_INDEX?编号范围:0 … N − 1相等 → 选入本分片test binary … --exact精确执行对应测试名
对应 workspace_root_test_launcher.sh.tpl 与 Windows 启动器。图示适用于已配置分片且未传额外 libtest 参数的路径;额外参数直接转交,未配置分片则不做哈希分组。测试用例 FNV-1a、CI 目标 cksum、远端 Worker 调度分属三个不同层次。

同一技术体系,不同服务实现:该版本 Codex 的 Bazel 配置使用 BuildBuddy 远端缓存与执行服务。它与 Buildfarm 共享 Bazel / Remote Execution API 技术体系,此处作为分布式构建与测试设计的公开源码参考。

工程关注点:吞吐、复用与可定位性

技术参考

Codex libtest FNV-1a 分片启动器 · Windows 对应实现

Buildfarm Shard / Backplane · Action Cache · Worker 流水线

Codex Windows CI 目标分片源码 · Codex 远端缓存与执行配置。源码参考固定于提交 40eeb6e8a89e;上述个人项目指标对应轻舟智航工作经验。