# Git Clone 下载速度测试报告

- 生成时间（UTC）：`2026-09-11T05:21:02Z`
- 清单文件：`/www/wwwroot/dataset/github_clone/star30_repos_not_cloned_part013.jsonl`
- 随机种子：`20260911`（可复现抽样）
- GitHub 认证账号：`guozhijian611`
- 主机：`s289364.nocix.net` · `Linux 6.8.0-41-generic` · 16 CPU · IP `74.91.24.26`
- Git：`git version 2.43.0`

## 1. 测试目的与结论摘要

本测试评估的是 **git clone（HTTPS）+ 内存 tar.gz 落盘** 这条真实流水线的速度，而不是 GitHub zipball / codeload 归档接口。

**顺序 shallow clone 的聚合下载吞吐量为 13.46 MiB/s**（payload 总和 / clone 时间总和）（均值 95% bootstrap CI：4.28 MiB/s – 10.25 MiB/s）。
**并发 4 的墙钟聚合吞吐量为 20.80 MiB/s**（payload 总和 / 阶段墙钟）。
**并发 8 的墙钟聚合吞吐量为 15.84 MiB/s**。

关键数字：

| 阶段 | 成功/总数 | clone 时间中位数 | clone 吞吐中位数 | 聚合 clone 吞吐 | 阶段墙钟 | 阶段 payload |
|---|---:|---:|---:|---:|---:|---:|
| 顺序 shallow x1 | 30/30 | 1.29 s | 5.14 MiB/s | 13.46 MiB/s | 3m 42.8s | 1.49 GiB |
| 并发 shallow x4 | 30/30 | 2.01 s | 7.56 MiB/s | 13.18 MiB/s | 1m 38.5s | 2.00 GiB |
| 并发 shallow x8 | 24/24 | 1.42 s | 4.07 MiB/s | 17.57 MiB/s | 3m 23.4s | 3.15 GiB |
| 顺序 full clone | 5/5 | 1.16 s | 3.19 MiB/s | 7.16 MiB/s | 37.07 s | 179.01 MiB |

## 2. 方法

### 2.1 为什么不做 54,349 个仓库的全量 clone

清单体量太大，全量跑一遍只能得到一个不可复现的墙钟数字，无法分离网络、Git 协议开销、压缩和落盘，也无法给出不确定度。本测试用 **有种子的分层随机抽样** 估计速度分布，再用样本率外推全量。

### 2.2 抽样

1. 读取清单全部 `54349` 条有效 `full_name`。
2. 以种子 `20260911` 无放回抽取 `600` 个仓库，调用 GitHub REST `GET /repos/{owner}/{repo}` 取 `size`（KiB）。
3. 按 GitHub `size` 分层：

| 层 | GitHub size | 含义 |
|---|---|---|
| XS | < 100 KiB | 极小 |
| S | 100 KiB – 1 MiB | 小 |
| M | 1 – 10 MiB | 中 |
| L | 10 – 50 MiB | 大 |
| XL | 50 – 200 MiB | 很大 |
| XXL | 200 MiB – 1 GiB | 极大 |
| TOO_LARGE | ≥ 1 GiB | 测速中排除，只统计占比 |

4. 每层再无放回切成互斥任务集，避免同一仓库被 GitHub/CDN 缓存后污染后续阶段：

- 顺序 shallow：每层 5 个
- 并发 4 shallow：每层 5 个
- 并发 8 shallow：每层 4 个
- 顺序 full clone：每层 1 个（不含 XXL）
- 顺序阶段前 2 个成功 clone 记为 warmup，**不进入统计**

### 2.3 每个仓库的流水线

1. `git clone` 到 tmpfs（`/dev/shm`），减少磁盘对「下载速度」的污染。
2. 主测模式：`--depth 1 --single-branch --no-tags`，对应 5 万级清单的可执行采集方式。
3. 对照模式：不带 depth 的 full clone，量化历史对象对时间和体积的放大。
4. `tarfile` + `SpooledTemporaryFile(max_size=256MiB)` 在内存中 `w:gz`（compresslevel=6），再 `fsync` 写到数据集盘。
5. 压缩包文件名：`{owner}__{reponame}.tar.gz`（两个下划线）。
6. 立刻删除工作树，不在磁盘上保留未打包 clone。
7. `GIT_LFS_SKIP_SMUDGE=1`，避免偶然 LFS 对象把单次样本变成异常值。

认证走 `http.extraHeader=Authorization: Basic base64(x-access-token:TOKEN)`。Git 智能 HTTP 不接受 REST 风格的 `Bearer`；带错误 Authorization 时 GitHub **不会**回退成匿名访问。clone URL 不含 token，日志已脱敏。

### 2.4 指标定义

| 指标 | 定义 |
|---|---|
| clone_s | `git clone` 墙钟 |
| clone_bytes | clone 工作树 `st_size` 总和（含 `.git`） |
| clone_bps | clone_bytes / clone_s。这是 **含 Git 握手、排队、解包** 的有效吞吐，不是纯 TCP |
| git_recv_bps | git 进度条里的 Receiving objects 速率（若有） |
| pack_s / write_s | 内存 tar.gz / 落盘+fsync |
| aggregate clone bps | Σ clone_bytes / Σ clone_s，体积加权，更接近「搬数据」 |
| 阶段墙钟吞吐 | Σ clone_bytes / 阶段 wall，并发时才有意义 |
| 均值 95% CI | 对 **每仓 clone_bps** 做 2000 次 bootstrap，反映小仓延迟对均值的拉动 |

小仓会严重拉低算术平均吞吐（固定 RTT/握手开销），所以报告同时给 **中位数、p90、体积加权聚合**。分层就是为了不让样本全是小仓。

## 3. 环境与网络基线

```
total        used        free      shared  buff/cache   available
内存：          62Gi       6.1Gi       699Mi        92Mi        57Gi        56Gi
交换：         8.0Gi       1.3Gi       6.7Gi
```

```
文件系统       类型   大小  已用  可用 已用% 挂载点
/dev/sda2      ext4   219G  103G  105G   50% /
tmpfs          tmpfs   32G  194M   32G    1% /dev/shm
/dev/sdb1      ext4   3.6T  1.7T  1.8T   48% /www/wwwroot/dataset
```

GitHub ping / TLS：

```
PING github.com (140.82.113.4) 56(84) bytes of data.
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=1 ttl=45 time=32.6 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=2 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=3 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=4 ttl=45 time=32.4 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=5 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=6 ttl=45 time=32.9 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=7 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=8 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=9 ttl=45 time=32.5 ms
64 bytes from lb-140-82-113-4-iad.github.com (140.82.113.4): icmp_seq=10 ttl=45 time=32.5 ms

--- github.com ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9013ms
rtt min/avg/max/mdev = 32.426/32.538/32.906/0.130 ms
```

```
http_code=200 namelookup=0.016685 connect=0.049788 appconnect=0.144477 ttfb=0.179801 total=0.378995 speed=1523413
```

### 3.1 HTTPS 归档下载基线（codeload，非 git 协议）

用于给 git 协议吞吐一个对照上限。第一次视为 warmup。

| run | warmup | size | wall | 吞吐 | http |
|---:|:---:|---:|---:|---:|---:|
| 1 | yes | 10.46 MiB | 4.03 s | 2.60 MiB/s | 200 |
| 2 | no | 10.46 MiB | 3.61 s | 2.90 MiB/s | 200 |
| 3 | no | 10.46 MiB | 2.53 s | 4.13 MiB/s | 200 |

## 4. 清单与 API 抽样

- 清单有效仓库数：54349
- API 抽样请求数：600
- API 成功拿到 size：515
- HTTP 404（已删/改名/私有）：84
- 其他 API 失败：1
- ≥ 1 GiB 排除：1

| 层 | API 样本数 | 占比 | size 中位数 (KiB) |
|---|---:|---:|---:|
| XS | 86 | 14.3% | 27 |
| S | 137 | 22.8% | 346 |
| M | 150 | 25.0% | 3483 |
| L | 82 | 13.7% | 20477 |
| XL | 38 | 6.3% | 99510 |
| XXL | 21 | 3.5% | 349011 |
| TOO_LARGE | 1 | 0.2% | 4125579 |
| UNKNOWN | 85 | 14.2% | None |

各测速阶段实际抽到的仓库见 `speed_test/reports/sample.json`。

## 5. 分阶段结果

### 5.1 顺序 shallow clone（并发 = 1）

- 墙钟：3m 42.8s
- 成功：30 / 30（100.0% ）
- payload 合计：1.49 GiB
- 归档合计：1.07 GiB
- clone 时间：mean 3.77 s · median 1.29 s · p90 12.53 s · p95 13.80 s · min 602 ms · max 14.01 s · sd 4.48 s
- clone 吞吐：mean 7.13 MiB/s · median 5.14 MiB/s · p90 15.85 MiB/s · p95 17.52 MiB/s · min 47.98 KiB/s · max 37.99 MiB/s · sd 8.34 MiB/s
- git 自报 Receiving 速率：n/a
- 体积加权聚合 clone 吞吐：13.46 MiB/s
- 阶段墙钟吞吐：6.83 MiB/s
- 内存打包：mean 3.13 s · median 513 ms · p90 11.58 s · p95 13.18 s · min 24 ms · max 15.32 s · sd 4.90 s
- 落盘+fsync：mean 421 ms · median 88 ms · p90 1.60 s · p95 1.80 s · min 25 ms · max 1.94 s · sd 620 ms
- 端到端（clone+pack+write+cleanup）：mean 7.43 s · median 1.91 s · p90 26.35 s · p95 28.53 s · min 674 ms · max 31.58 s · sd 10.00 s
- 每仓 clone_bps 均值 95% CI：4.28 MiB/s – 10.25 MiB/s

| 层 | 成功/N | payload 中位 | clone 中位 | clone 吞吐中位 | 聚合吞吐 |
|---|---:|---:|---:|---:|---:|
| XS | 5/5 | 93.14 KiB | 644 ms | 108.89 KiB/s | 133.76 KiB/s |
| S | 5/5 | 377.02 KiB | 892 ms | 505.66 KiB/s | 908.13 KiB/s |
| M | 5/5 | 8.37 MiB | 1.26 s | 7.05 MiB/s | 6.98 MiB/s |
| L | 5/5 | 3.78 MiB | 1.50 s | 2.52 MiB/s | 9.22 MiB/s |
| XL | 5/5 | 184.11 MiB | 13.57 s | 13.57 MiB/s | 13.62 MiB/s |
| XXL | 5/5 | 152.23 MiB | 5.95 s | 15.62 MiB/s | 18.28 MiB/s |

### 5.2 并发 4 shallow clone

- 墙钟：1m 38.5s
- 成功：30 / 30（100.0% ）
- payload 合计：2.00 GiB
- 归档合计：1.58 GiB
- clone 时间：mean 5.18 s · median 2.01 s · p90 13.40 s · p95 19.41 s · min 530 ms · max 20.48 s · sd 6.18 s
- clone 吞吐：mean 7.30 MiB/s · median 7.56 MiB/s · p90 16.00 MiB/s · p95 16.39 MiB/s · min 81.96 KiB/s · max 23.62 MiB/s · sd 6.44 MiB/s
- git 自报 Receiving 速率：n/a
- 体积加权聚合 clone 吞吐：13.18 MiB/s
- 阶段墙钟吞吐：20.80 MiB/s
- 内存打包：mean 4.16 s · median 920 ms · p90 10.56 s · p95 19.52 s · min 26 ms · max 26.49 s · sd 6.72 s
- 落盘+fsync：mean 711 ms · median 211 ms · p90 2.24 s · p95 2.41 s · min 30 ms · max 3.54 s · sd 926 ms
- 端到端（clone+pack+write+cleanup）：mean 10.17 s · median 3.18 s · p90 24.68 s · p95 43.14 s · min 599 ms · max 48.65 s · sd 13.76 s
- 每仓 clone_bps 均值 95% CI：5.04 MiB/s – 9.63 MiB/s

| 层 | 成功/N | payload 中位 | clone 中位 | clone 吞吐中位 | 聚合吞吐 |
|---|---:|---:|---:|---:|---:|
| XS | 5/5 | 158.57 KiB | 577 ms | 173.22 KiB/s | 197.25 KiB/s |
| S | 5/5 | 407.32 KiB | 694 ms | 432.47 KiB/s | 600.68 KiB/s |
| M | 5/5 | 11.04 MiB | 1.30 s | 7.33 MiB/s | 7.33 MiB/s |
| L | 5/5 | 19.31 MiB | 2.68 s | 7.79 MiB/s | 7.50 MiB/s |
| XL | 5/5 | 138.77 MiB | 11.15 s | 12.42 MiB/s | 12.87 MiB/s |
| XXL | 5/5 | 137.78 MiB | 10.29 s | 16.24 MiB/s | 17.05 MiB/s |

### 5.3 并发 8 shallow clone

- 墙钟：3m 23.4s
- 成功：24 / 24（100.0% ）
- payload 合计：3.15 GiB
- 归档合计：2.04 GiB
- clone 时间：mean 7.64 s · median 1.42 s · p90 16.99 s · p95 19.67 s · min 590 ms · max 1m 18.0s · sd 16.08 s
- clone 吞吐：mean 6.83 MiB/s · median 4.07 MiB/s · p90 15.44 MiB/s · p95 16.62 MiB/s · min 41.34 KiB/s · max 25.82 MiB/s · sd 6.95 MiB/s
- git 自报 Receiving 速率：n/a
- 体积加权聚合 clone 吞吐：17.57 MiB/s
- 阶段墙钟吞吐：15.84 MiB/s
- 内存打包：mean 7.87 s · median 519 ms · p90 14.58 s · p95 18.73 s · min 25 ms · max 1m 45.3s · sd 21.50 s
- 落盘+fsync：mean 1.09 s · median 112 ms · p90 3.37 s · p95 4.82 s · min 29 ms · max 11.87 s · sd 2.62 s
- 端到端（clone+pack+write+cleanup）：mean 16.81 s · median 2.20 s · p90 33.65 s · p95 43.31 s · min 649 ms · max 3m 16.1s · sd 40.25 s
- 每仓 clone_bps 均值 95% CI：4.25 MiB/s – 9.75 MiB/s

| 层 | 成功/N | payload 中位 | clone 中位 | clone 吞吐中位 | 聚合吞吐 |
|---|---:|---:|---:|---:|---:|
| XS | 4/4 | 87.05 KiB | 782 ms | 81.07 KiB/s | 286.57 KiB/s |
| S | 4/4 | 1.52 MiB | 874 ms | 1.78 MiB/s | 1.62 MiB/s |
| M | 4/4 | 3.30 MiB | 1.06 s | 2.24 MiB/s | 2.98 MiB/s |
| L | 4/4 | 34.63 MiB | 2.54 s | 13.51 MiB/s | 12.72 MiB/s |
| XL | 4/4 | 127.35 MiB | 12.91 s | 10.15 MiB/s | 12.38 MiB/s |
| XXL | 4/4 | 160.24 MiB | 11.31 s | 12.89 MiB/s | 22.47 MiB/s |

### 5.4 顺序 full clone 对照

- 墙钟：37.07 s
- 成功：5 / 5（100.0% ）
- payload 合计：179.01 MiB
- 归档合计：149.78 MiB
- clone 时间：mean 5.00 s · median 1.16 s · p90 12.18 s · p95 14.09 s · min 655 ms · max 16.00 s · sd 6.61 s
- clone 吞吐：mean 4.21 MiB/s · median 3.19 MiB/s · p90 8.20 MiB/s · p95 8.49 MiB/s · min 203.66 KiB/s · max 8.78 MiB/s · sd 3.70 MiB/s
- git 自报 Receiving 速率：n/a
- 体积加权聚合 clone 吞吐：7.16 MiB/s
- 阶段墙钟吞吐：4.83 MiB/s
- 内存打包：mean 2.05 s · median 323 ms · p90 5.26 s · p95 6.02 s · min 49 ms · max 6.77 s · sd 2.91 s
- 落盘+fsync：mean 331 ms · median 65 ms · p90 784 ms · p95 861 ms · min 47 ms · max 937 ms · sd 403 ms
- 端到端（clone+pack+write+cleanup）：mean 7.41 s · median 1.59 s · p90 18.28 s · p95 21.02 s · min 758 ms · max 23.77 s · sd 9.94 s
- 每仓 clone_bps 均值 95% CI：1.40 MiB/s – 7.08 MiB/s

| 层 | 成功/N | payload 中位 | clone 中位 | clone 吞吐中位 | 聚合吞吐 |
|---|---:|---:|---:|---:|---:|
| XS | 1/1 | 133.30 KiB | 655 ms | 203.66 KiB/s | 203.66 KiB/s |
| S | 1/1 | 1.14 MiB | 734 ms | 1.55 MiB/s | 1.55 MiB/s |
| M | 1/1 | 3.71 MiB | 1.16 s | 3.19 MiB/s | 3.19 MiB/s |
| L | 1/1 | 56.71 MiB | 6.46 s | 8.78 MiB/s | 8.78 MiB/s |
| XL | 1/1 | 117.32 MiB | 16.00 s | 7.33 MiB/s | 7.33 MiB/s |

## 6. 分层对速度的影响

Git clone 有接近固定的 HTTPS/Git 握手成本。小仓的 clone_bps 会被延迟主导，大仓才接近链路带宽。因此：

- **不要只用全样本平均值描述「下载速度」。**
- 体积加权聚合吞吐更接近搬迁 54k 仓时「有效带宽」的概念。
- 并发提升的是墙钟吞吐；单连接速率不一定变。

## 7. 外推到全量清单

测速阶段对每层抽了同样多的仓库（XS 和 XXL 各 5 个），所以 **顺序阶段的样本均值 50.75 MiB/仓会被大仓拉高**，不能直接乘 54,349。正确做法是用 API 样本的层权重，把各层观测到的均值还原到总体。

API 600 仓 → 总体权重（N = 54,349）：

| 层 | API 计数 | 期望仓数 | 该层 shallow 均 payload | 该层均 clone | 该层均端到端 |
|---|---:|---:|---:|---:|---:|
| 404 | 84 | 7,609 | — | — | — |
| XS | 86 | 7,790 | 151 KiB | 0.74 s | 0.83 s |
| S | 137 | 12,410 | 875 KiB | 0.85 s | 1.09 s |
| M | 150 | 13,587 | 8.16 MiB | 1.33 s | 2.07 s |
| L | 82 | 7,428 | 31.32 MiB | 3.12 s | 5.90 s |
| XL | 38 | 3,442 | 149.45 MiB | 11.53 s | 22.59 s |
| XXL | 21 | 1,902 | 295.33 MiB | 14.73 s | 34.04 s |
| TOO_LARGE | 1 | 91 | 排除出测速 | — | — |
| UNKNOWN | 1 | 91 | — | — | — |

层加权（只对可 clone 的 XS–XXL，约 46,559 仓）点估计：

- API 存活率：85.8%（404 = 14.0%）
- 期望可 clone 仓数：≈ **46,559**
- 期望 ≥1 GiB、需单独队列：≈ **91**
- 层加权平均 payload：30.75 MiB/仓（比均等分层样本均值低 1.65×）
- 期望 shallow 工作树总量：≈ **1.40 TiB**
- 期望 `owner__reponame.tar.gz` 总量：≈ **1.00 TiB**（压缩比约 0.71）
- 严格串行（clone+内存打包+落盘）：≈ **65.1 小时**
- 串行只算 clone：≈ **34.8 小时**
- 并发 4，按本测观测到的并行效率 77%（相对 4× 理想）：≈ **21.0 小时**
- 并发 8，按本测观测到的并行效率 25%（被 1.97 GiB 的 straggler 拖死）：≈ **32.8 小时**，**比并发 4 更慢**

结论：生产采集用 **并发 4 + 按 size 分队列**（XS/S/M 一条，L/XL 一条，XXL/≥1GiB 单独）。不要先上 8：本测并发 8 的墙钟吞吐 15.84 MiB/s，低于并发 4 的 20.80 MiB/s。

这是单次观测的点估计，不是保证。404 仓不会变成归档；≥1 GiB 仓会额外加时间。

## 8. 科学局限

1. **时间点**：GitHub 边缘节点负载随小时变化，本报告是单次观测。
2. **浅克隆 ≠ 全历史**：主数字是 `--depth 1`。full clone 对照用来标定历史放大系数。
3. **GitHub `size` 含完整对象库**，shallow 工作树通常更小，分层用 API size 只保证「大仓/小仓」排序，不保证字节数相等。
4. **LFS 被跳过**。若生产需要 LFS 实文件，吞吐会被个别仓拖死，需单独策略。
5. **删除/改名/私有仓**：404 比例会进入外推，但不会变成归档。
6. **二次 clone 会偏快**：阶段之间仓库互斥，但 GitHub 对热门仓仍可能命中服务端缓存。
7. **内存打包**：超过 256 MiB 的归档会溢到磁盘 spool，指标里有 `spool_spilled`。
8. **token**：classic PAT 仅通过环境变量注入，未写入仓库文件。该 token 已在对话中出现，用完应立刻轮换。

## 9. 对后续全量采集的建议

- 生产默认：`git clone --depth 1 --single-branch --no-tags`，认证 header，跳过 LFS smudge。
- 并发先用 4，看失败率和墙钟吞吐；若稳定再试 8。
- 单仓超时：shallow 180s，full 420s；低速断开 `http.lowSpeedLimit=1000` / `lowSpeedTime=60`。
- 归档名严格执行 `owner__reponame.tar.gz`；工作树打进包内的顶层目录同名（无 `.tar.gz`）。
- 先 API 探活再 clone，避免给 404 付握手成本。
- ≥1 GiB 仓单独队列，不要和中小仓混在同一个线程池。

## 10. 产物路径

- 归档目录：`/www/wwwroot/dataset/github_clone/speed_test/archives`
- 每仓指标：`/www/wwwroot/dataset/github_clone/speed_test/reports/metrics.jsonl`
- 抽样清单：`/www/wwwroot/dataset/github_clone/speed_test/reports/sample.json`
- 环境快照：`/www/wwwroot/dataset/github_clone/speed_test/reports/environment.json`
- JSON 摘要：`/www/wwwroot/dataset/github_clone/speed_test/reports/summary.json`
- 运行日志：`/www/wwwroot/dataset/github_clone/speed_test/logs/run.log`

归档命名抽查：

- `0xTriboulet__emerald_template.tar.gz`
- `1hAck-0__UE4-Cheat-Source-Code.tar.gz`
- `Abdelazim-Abdelgawwad__easyPARM.tar.gz`
- `Adobe-CEP__Getting-Started-guides.tar.gz`
- `Data-X01__PsychLing-101.tar.gz`
- `DavidDragonsage__FooocusPlus.tar.gz`
- `EBonura__bonnie-32.tar.gz`
- `FreeMovieIR__freemovieir.github.io.tar.gz`
- `FuchsTom__ProdSim.tar.gz`
- `GHkmmm__laizan.tar.gz`
- `HalfSweet__FuckJLCColorfulSilkscreen.tar.gz`
- `Henglie__ElegantHLK.tar.gz`
- `HybridRobotics__Ego-VCP.tar.gz`
- `IgorAherne__TRELLIS.2-stableprojectorz.tar.gz`
- `Imageomics__Prompt_CAM.tar.gz`
- … 共 91 个

