浏览器无法发送原始 ping,测速只能给 HTTP 传输计时。看懂预热、负载大小、并发流与中位数,如何决定你最终看到的那个数字。
核心要点
- 网页无法发送 ICMP ping,也不能打开原始套接字,因此所有浏览器测速都由用时钟计时的 HTTP 或 WebSocket 传输构成。
- 吞吐量就是收到的字节数除以耗时,但要等连接提速完成后才有意义,所以测速会先做预热传输,并丢弃最初的那几秒。
- 测试设计上的选择(单流还是并发流、负载大小、取中位数还是最佳一次)会让同一条线路测出不同的最终结果。
- 浏览器里的"ping"其实是一次 HTTP 往返,包含服务器处理时间,而不只是线路本身。
浏览器测速的原理,是通过 HTTP(或 WebSocket)传输真实字节,并用高精度时钟计时。下载速度就是收到的数据量除以所用时间;延迟则是一个极小请求与响应的往返时间。测试设计里的其余环节,都是为了让这道简单的除法算得真实可信。本文只讲机制:传了什么、计时的是什么、丢弃了什么、最后如何得出一个数字。至于为什么不同次数或不同工具的结果会不一样,请看测速结果为何会变;带宽、延迟和抖动的含义,请看测速指标详解。
浏览器到底能测什么?
网页运行在沙箱里。它不能发送 ICMP 回显请求(经典的 ping),不能打开原始套接字,也看不到数据包。它能做的是调用 fetch()、XMLHttpRequest 或 WebSocket,并读取时钟。标准时钟是 performance.now(),这是一个单调计时器,不受系统时间调整影响。
这一个限制,几乎解释了全部设计:
- 延迟是一次 HTTP 往返。 浏览器给一个小请求计时,直到响应到达。其中包含服务器处理时间和连接处理开销,因此通常会比对同一主机的 ICMP ping 略高。
- 吞吐量是站在页面一侧观察到的。 测试在数据到达时(或上传完成时)统计字节数,再除以耗时。它测的是页面实际能搬运多少数据,这正是上网时真正有意义的数字。
为什么测速需要预热
新的 TCP 连接不会一上来就满速。拥塞控制从很小的窗口开始,随着确认包返回逐步放大,这一阶段称为慢启动。如果只给一个小文件计时,测到的主要是这段爬升过程,会低估线路能力。
IETF 的 TCP 吞吐量测试框架 RFC 6349 也强调了同一点:你想知道的是路径能够持续维持的稳态吞吐量,而不是最初的几个往返。实践中测速工具用两种办法应对:先发一个结果会被丢弃的预热请求;再用足够大的负载,让爬升阶段只占总时间的一小部分。
这也解释了为什么极小的文件不适合测带宽。1 KB 的响应在窗口打开之前就结束了,它反映的是延迟,而不是容量。
自适应的负载大小
固定的文件大小对大多数人都不合适。50 MB 的文件在较弱的移动网络上要几分钟;在光纤上,1 MB 的文件在连接爬升之前就传完了。常见做法是从小开始,逐步增大负载,直到一次传输达到目标时长,通常是几秒。慢速线路保持较短,快速线路则能拿到足够的数据进入稳态。
一条流还是多条流?
这里各家设计确实不同。
- 多条并发流。 许多商业测速会同时打开多条 TCP 连接。这样能填满带宽时延积很高(又快又远)、单条流跑不满的线路,报出的峰值也往往更高。
- 单条流。 M-Lab 的 NDT 当前的 ndt7 形态刻意在固定时长内只用一条连接,其协议规范规定通过 WebSocket 传输。只用一条连接正是它的用意:它要测的是单条 TCP 流在这条路径上能跑多快。
两者都没错,只是回答不同的问题:"这条线路总共能承载多少?"与"一条连接能拿到多少?"。单流在极快的线路上读数可能偏低;而如果一条路径上的实际流量大多是单连接,多流测速就可能把它测得过于乐观。
从样本到一个数字
测试会采集许多测量值,然后要汇总成一个最终数字。选择不同,结果不同:
| 汇总方式 | 影响 |
|---|---|
| 所有次数的平均值 | 会被缓慢的爬升和偶发卡顿拉低 |
| 中位数 | 抗离群值,数字稳定而偏保守 |
| 最佳一次(或高分位) | 数字最高,最接近峰值容量,也最不典型 |
| 截尾平均(去掉最高和最低) | 介于两者之间的折中 |
同一条线路、同样的原始样本,仅因工具选了其中不同的一种,显示出的结果就可能明显不同。
负载下的延迟
空闲延迟与链路繁忙时的延迟是两种不同的测量。安静时 ping 15 毫秒的线路,一旦传输填满缓冲区,可能跳到几百毫秒。IETF IPPM 工作组的响应性草案把这种测量形式化,以每分钟往返次数表示。大多数浏览器测速只报告空闲延迟。如果你的延迟在负载下飙升,请看缓冲区膨胀(Bufferbloat)详解。
抖动是算出来的,不是观察到的
没有人直接测量抖动。测试发送一系列小请求,记录每次延迟,再从这个序列推导出抖动。各工具的公式并不一致:相邻样本差值的平均绝对值、全部样本的标准差,或像 RFC 3550 中那样的平滑滚动估计。同样的数据会得出不同的数字,所以抖动只应在同一工具的多次运行之间比较。关于抖动对通话和游戏的影响,请看抖动与丢包详解。
BrowserInsight 的测速是怎么做的
作为具体例子,下面是我们的测速工具的做法,这只是若干合理设计中的一种:
- 传输: 向我们自己的边缘端点发送 HTTP 请求,一次一条流(顺序执行,不并行)。
- 预热: 下载和上传阶段之前,先发一个约 30 KB 的请求,其结果被丢弃。
- 负载大小: 下载依次传输 200 KB、1 MB、3 MB,之后按约两秒的传输时长自适应调整,上限 10 MB。上传大小则根据首次 200 KB 上传的速度来放大。
- 时长: 下载阶段要同时满足 15 秒和至少三次传输才结束,最长 30 秒或十次传输;上传阶段最多三次传输。
- 计时: 每次传输从发出请求开始计时,到最后一个字节到达(或上传得到确认)为止,因此每个样本都包含一次往返。
- 最终吞吐量: 每个阶段各次计时传输的中位数。
- 延迟: 丢弃一次预备请求后,三次 1 KB HTTP 请求的平均值。
- 抖动: 相邻延迟样本差值的平均绝对值。
取舍很明确:单流反映一条连接能拿到什么,但在极快线路上可能比多流测速读数更低。只有三个延迟样本,也意味着抖动数值比较粗略,适合作快速参考,不宜据此判定通话质量。它不使用 ICMP,不并行多流,也不测量负载下的延迟。
阅读任何测速方法说明的检查清单
在相信一个数字之前,看看:
- 流数: 一条连接还是多条?
- 时长: 固定时间,还是固定文件大小?
- 预热: 爬升阶段是否被丢弃,怎么丢弃?
- 汇总: 中位数、平均值,还是最佳一次?
- 服务器距离: 测试端点离你有多远?
- 延迟定义: 空闲还是负载下,HTTP 还是 ICMP?
能把这些问题坦白讲清楚的工具,比单纯数字更大的工具更值得信赖。
常见问题
网站能用 ICMP 测我的 ping 吗?
不能。浏览器不向网页开放 ICMP 或原始套接字。浏览器里的"ping"是一次小型 HTTP 或 WebSocket 往返的耗时,其中包含一些服务器处理时间。
为什么测速会先下载一个丢弃的文件?
为了越过 TCP 慢启动。新连接从较小的拥塞窗口开始,最初的字节传得很慢。预热传输(或丢弃早期区间)能让测量反映稳态吞吐量。
单流测速比多流测速不准吗?
不是更不准,而是回答的问题不同。单流测的是一条 TCP 流能达到多少;多流测的是线路的总容量。在极快的线路上,单流的读数可能更低。
为什么浏览器里的延迟比命令行 ping 更高?
HTTP 延迟在网络往返之上,还包含服务器处理和连接处理,而 ICMP ping 只测后者。
总结
浏览器测速是一组计时的 HTTP 传输,其形态由网页被允许做的事决定。预热处理、负载大小、流数和汇总方式对最终数字的影响,远超多数人的想象。带着这些问题去读测速方法说明,再对照上面的设计,用我们的网络测速实际测一次。
推荐阅读:


