32名工人是最佳选择 | AI生成和翻译

Home 2026.06

为什么 32 是 M2 Air 的最佳并发数

工作负载解析

每次 git fetch 的执行流程如下:

线程空闲(99%的时间)
├── DNS 查找 → GitHub
├── TCP 握手 → GitHub
├── SSH 密钥交换 / TLS 握手
├── Git 协议:"你有什么引用?"
├── Git 协议:"这是精简包"
├── 将包文件写入 .git/objects/pack/
└── 线程再次空闲

CPU 几乎无事可做——仅在最后进行 SHA-1 哈希验证。线程 99% 的时间都在等待两件事:

  1. 与 GitHub 的网络往返——从广州(通过 DMIT/hysteria2 途经洛杉矶代理)每次请求约 50-200ms。这是 50-200ms 的纯等待时间,线程处于休眠状态,CPU 核心完全空闲。

  2. 磁盘写入——你的 SSD 写入包文件仅需微秒级别。可忽略不计。

为什么 CPU 核心数在此不关键

你的 M2 有 8 个核心(4 大核 + 4 小核)。如果是 CPU 密集型任务(如视频编码),8 个线程就能占满所有核心,32 个线程只会增加上下文切换的开销。

但对于 I/O 密集型工作,等待网络数据包的线程消耗 0% CPU。它被挂起在内核的 epoll/kqueue 中——无需调度,不消耗时钟周期。因此你可以让 32 或 64 个线程同时处于”活跃”状态,而总 CPU 占用率可能只有 2-3%。

你机器上的数学计算

160 个仓库 × 约 150ms 平均网络 RTT(广州 → 洛杉矶代理 → GitHub)

使用 8 个工作者:
  160 / 8 = 20 批 × 150ms = 理论最小值 3.0s
  实际:24.1s(包含 SSH 建立、DNS、部分慢仓库)

使用 32 个工作者:
  160 / 32 = 5 批 × 150ms = 理论最小值 0.75s
  实际:9.9s(4 批遭遇慢尾延迟)

使用 64 个工作者:
  160 / 64 = 2.5 批 → 3 批 × 150ms = 理论值 0.45s
  实际:9.6s——仅比 32 快 0.3s

为什么 64 提升不大

三大瓶颈:

  1. GitHub 连接限流——GitHub 限制每个 IP 的并发 SSH 连接数。超过约 30-40 个后,新连接会开始在服务器端排队。你在 32 个时就遇到了这个瓶颈。

  2. DMIT 代理瓶颈——你的流量通过 hysteria2 → 洛杉矶 → GitHub。代理有自己的连接池和带宽限制。32 个并发流已经使其饱和。

  3. macOS 文件描述符开销——每个 git 进程打开约 5-10 个文件描述符(套接字、包文件、索引等)。32 个工作者时约 200-300 个 FD,远在你的 ulimit -n 2560 限制内。64 个时仍然没问题,但内核的 kqueue 需要做更多轮询工作。

为什么不选 128 或 256

工作者数   批次数   GitHub 排队   净收益
───────   ───────   ──────────   ──────
   8        20         无         基准值
  32         5         轻微       快 2.4 倍
  64         3         中等       快 2.5 倍
 128         2         严重       ~2.5 倍(无提升)
 256         1         严重       可能更慢

当达到 128+ 时,你建立连接的速度超过 GitHub 的接受速度,连接在内核的 TCP 积压队列中排队。你并没有加快获取速度——只是将队列从”你的线程池”转移到了”GitHub 的限流器”。同样的瓶颈,不同的队列。

结论

对于 CPU 密集型任务,最佳工作者数 = CPU 核心数(你的 M2 为 8)。对于像 git fetch 这样的 I/O 密集型任务,最佳工作者数 = 远程服务器和你的网络路径能同时处理的并发网络请求数。对于从广州通过洛杉矶代理访问 GitHub 的情况,这个数字约为 32。


Back Donate