bigywater.tech
网络协议 · 64

丢包率对 TCP 吞吐的影响:用延迟与丢包注入实测

丢包对 TCP 的伤害远比“丢了几个包”大得多:每次丢包都让发送方把窗口缩小。这篇用 netlab 在回环上造出 20 ms 和 100 ms 的往返时间,逐档注入 0.1% 到 5% 的随机丢包,看吞吐掉多少、和教科书上的 Mathis 公式吻合到什么程度、RTT 和丢包率各自的影响。

2.2%
5% 丢包时的吞吐占无丢包基线的比例(往返 20 ms 与 100 ms 都是 2.2%)
0.89 ~ 1.21
除一格外,实测吞吐与 Mathis 公式预测之比的范围
0.08% ~ 5.77%
往返 20 ms 下重传字节占比随丢包率从 0.1% 到 5% 的变化

基线与丢包的代价

实测 · 本机执行输出
  RTT  20 ms,丢包   0%:吞吐  193.57 MB/s(两次 192.62 / 194.53)
  RTT  20 ms,丢包 0.1%:吞吐   31.70 MB/s(两次 25.95 / 37.44)
  RTT  20 ms,丢包 0.5%:吞吐   15.76 MB/s(两次 15.37 / 16.16)
  RTT  20 ms,丢包   1%:吞吐   10.22 MB/s(两次 11.60 / 8.85)
  RTT  20 ms,丢包   2%:吞吐    7.29 MB/s(两次 7.63 / 6.94)
  RTT  20 ms,丢包   5%:吞吐    4.19 MB/s(两次 4.65 / 3.72)
  RTT 100 ms,丢包   0%:吞吐   41.46 MB/s(两次 41.45 / 41.47)
  RTT 100 ms,丢包 0.1%:吞吐   11.70 MB/s(两次 14.45 / 8.94)
  RTT 100 ms,丢包 0.5%:吞吐    3.42 MB/s(两次 3.83 / 3.01)
  RTT 100 ms,丢包   1%:吞吐    1.78 MB/s(两次 1.79 / 1.76)
  RTT 100 ms,丢包   2%:吞吐    1.40 MB/s(两次 1.36 / 1.45)
  RTT 100 ms,丢包   5%:吞吐    0.90 MB/s(两次 0.93 / 0.88)

无丢包时吞吐被 4 MiB 窗口卡住:20 ms 往返 193.57 MB/s,100 ms 往返 41.46 MB/s。0.1% 的丢包让吞吐剩 16%~28%;5% 丢包只剩 2.2%。

与公式对照

实测 · 本机执行输出
  往返 20 ms(无丢包基线 193.57 MB/s):
    丢包率    吞吐(MB/s)    相对基线     Mathis 预测(MB/s)   实测 ÷ 预测
        0%       193.57      100.0%            —                  —
      0.1%        31.70       16.4%            31.50            1.01
      0.5%        15.76        8.1%            14.09            1.12
        1%        10.22        5.3%             9.96            1.03
        2%         7.29        3.8%             7.04            1.03
        5%         4.19        2.2%             4.46            0.94
  往返 100 ms(无丢包基线 41.46 MB/s):
    丢包率    吞吐(MB/s)    相对基线     Mathis 预测(MB/s)   实测 ÷ 预测
        0%        41.46      100.0%            —                  —
      0.1%        11.70       28.2%             6.30            1.86
      0.5%         3.42        8.3%             2.82            1.21
        1%         1.78        4.3%             1.99            0.89
        2%         1.40        3.4%             1.41            1.00
        5%         0.90        2.2%             0.89            1.01
  (Mathis 公式 吞吐 ≈ 1.22 × MSS ÷ (RTT × √p) 是计算值,p 取单向丢包率;实际丢包经过数据与 ACK 两个方向,公式只是个量级参考)

吞吐 ≈ 1.22×MSS÷(RTT×√p):大多数格子实测与预测之比在 0.89~1.21。

RTT 的影响

实测 · 本机执行输出
  丢包 0.1%:RTT 20 ms 吞吐   31.70 MB/s,RTT 100 ms 吞吐   11.70 MB/s,比值 2.7(公式预测 RTT 反比 = 5.0)
  丢包 0.5%:RTT 20 ms 吞吐   15.76 MB/s,RTT 100 ms 吞吐    3.42 MB/s,比值 4.6(公式预测 RTT 反比 = 5.0)
  丢包   1%:RTT 20 ms 吞吐   10.22 MB/s,RTT 100 ms 吞吐    1.78 MB/s,比值 5.8(公式预测 RTT 反比 = 5.0)
  丢包   2%:RTT 20 ms 吞吐    7.29 MB/s,RTT 100 ms 吞吐    1.40 MB/s,比值 5.2(公式预测 RTT 反比 = 5.0)
  丢包   5%:RTT 20 ms 吞吐    4.19 MB/s,RTT 100 ms 吞吐    0.90 MB/s,比值 4.6(公式预测 RTT 反比 = 5.0)

同样的丢包率,RTT 5 倍,吞吐之比约 4.6~5.8(0.1% 那一格是 2.7)。

丢包率的影响

实测 · 本机执行输出
  往返 20 ms:丢包 0.5% → 2%(×4):吞吐 ÷ 2.16(公式预测 ÷ 2.00)
  往返 20 ms:丢包 0.1% → 0.5%(×5):吞吐 ÷ 2.01(公式预测 ÷ 2.24)
  往返 20 ms:丢包 1% → 5%(×5):吞吐 ÷ 2.44(公式预测 ÷ 2.24)
  往返 100 ms:丢包 0.5% → 2%(×4):吞吐 ÷ 2.44(公式预测 ÷ 2.00)
  往返 100 ms:丢包 0.1% → 0.5%(×5):吞吐 ÷ 3.42(公式预测 ÷ 2.24)
  往返 100 ms:丢包 1% → 5%(×5):吞吐 ÷ 1.97(公式预测 ÷ 2.24)

丢包率 ×4,吞吐约 ÷2.2~2.4,符合 1/√p 的量级。

重传占比

实测 · 本机执行输出
    RTT(ms)   丢包率    重传字节占比     重传包数 / 发送包数
        20     0.1%        0.08%     19 / 23637
        20     0.5%        0.42%     34 / 8226
        20       1%        1.17%     55 / 4777
        20       2%        1.99%     80 / 4024
        20       5%        5.77%     118 / 2005
       100     0.1%        0.10%     5 / 4596
       100     0.5%        0.61%     11 / 1830
       100       1%        1.11%     10 / 939
       100       2%        2.60%     29 / 1066
       100       5%        4.20%     27 / 606

重传字节占比约等于丢包率,吞吐下降的主要原因是窗口缩小而不是重传的带宽。

分步演示

丢包与吞吐
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64(Apple 芯片)/ Python 3.14.8 / tcpdump(libpcap)/ scapy 2.8 / dpkt / dnspython / h2 / aioquic / OpenSSL / curl 8.7.1;抓包在 lo0(环回)上做,少数实验用真实网卡 en0(这台机器上 en0 是 Wi-Fi,tcpdump 看到的是系统转成以太网格式的帧,所以文中的“以太网头”都指这个 14 字节的头)或访问公网(会在文章里注明);需要丢包 / 延迟 / 限速时,用一个只作用于 lo0 端口 9400-9499 的 dummynet 辅助脚本(netlab);所有服务端都是本机自己起的进程;时间戳取自 tcpdump 的 -tt,数字每次运行会有小幅抖动。全部在 lo0 上(MSS 载荷 16332 字节),netlab 注入每方向延迟 10/50 ms 与单向独立随机丢包;每个组合只测 2 次,每次 5.5 秒窗口,随机丢包下波动大(例如 0.1% 的两次差 30%~60%),表中取均值;发送与接收在同一个进程的线程里
    • 没有验证:真实广域网的丢包模式(突发丢包与随机丢包差别很大,netlab 只造随机丢包);不同拥塞算法(BBR)对丢包的敏感度,本机无法切换;ECN 标记代替丢包的效果;和 w53 的 CUBIC 对比中 Mathis 比值的差别(w53 的 1.04~2.73 与本篇的 0.89~1.21 来自不同的实验设置,没有逐项对齐)
    京ICP备2026067502号-1京公网安备11010502063487号