瀏覽器無法傳送原始 ping,測速只能替 HTTP 傳輸計時。看懂預熱、負載大小、並行串流與中位數,如何決定你最終看到的那個數字。
重點摘要
- 網頁無法傳送 ICMP ping,也不能開啟原始 socket,因此所有瀏覽器測速都由用時鐘計時的 HTTP 或 WebSocket 傳輸組成。
- 吞吐量就是收到的位元組數除以耗時,但要等連線提速完成後才有意義,所以測速會先做預熱傳輸,並丟棄最初的幾秒。
- 測試設計上的選擇(單串流或並行串流、負載大小、取中位數或最佳一次)會讓同一條線路測出不同的最終結果。
- 瀏覽器裡的「ping」其實是一次 HTTP 往返,包含伺服器處理時間,而不只是線路本身。
瀏覽器測速的原理,是透過 HTTP(或 WebSocket)傳輸真實位元組,並用高精度時鐘計時。下載速度就是收到的資料量除以所用時間;延遲則是一個極小請求與回應的往返時間。測試設計裡的其餘環節,都是為了讓這道簡單的除法算得真實可信。本文只談機制:傳了什麼、計時的是什麼、丟棄了什麼、最後如何得出一個數字。至於為什麼不同次數或不同工具的結果會不一樣,請看測速結果為何會變;頻寬、延遲和抖動的意義,請看測速指標詳解。
瀏覽器到底能測什麼?
網頁執行在沙箱裡。它不能傳送 ICMP 回應請求(經典的 ping),不能開啟原始 socket,也看不到封包。它能做的是呼叫 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 或原始 socket。瀏覽器裡的「ping」是一次小型 HTTP 或 WebSocket 往返的耗時,其中包含一些伺服器處理時間。
為什麼測速會先下載一個丟棄的檔案?
為了越過 TCP 慢啟動。新連線從較小的壅塞視窗開始,最初的位元組傳得很慢。預熱傳輸(或丟棄早期區間)能讓測量反映穩態吞吐量。
單串流測速比多串流測速不準嗎?
不是更不準,而是回答的問題不同。單串流測的是一條 TCP 串流能達到多少;多串流測的是線路的總容量。在極快的線路上,單串流的讀數可能更低。
為什麼瀏覽器裡的延遲比命令列 ping 更高?
HTTP 延遲在網路往返之上,還包含伺服器處理和連線處理,而 ICMP ping 只測後者。
結論
瀏覽器測速是一組計時的 HTTP 傳輸,其形態由網頁被允許做的事決定。預熱處理、負載大小、串流數和彙總方式對最終數字的影響,遠超多數人的想像。帶著這些問題去讀測速方法說明,再對照上面的設計,用我們的網路測速實際測一次。
推薦閱讀:


