跳到主要內容

大量小檔案傳輸實測:rsync、tar、SFTP、TCP 與 QUIC 比較

從德國到美國,在 141 ms 往返延遲下傳送 65,536 個小檔案。實測 rsync、tar、Btrfs 快照、完整磁碟映像,以及 TCP/QUIC 與不同壅塞控制設定。

WarpSend 工程團隊 內容查核 Charlie 3 分鐘閱讀

我想知道,一個裝滿小檔案的目錄,複製起來到底慢在哪裡。我測了 rsync、串流 tar、快照複寫與完整磁碟映像複製,再用一個簡單的 Rust 傳輸程式調整傳輸設定。

資料是 65,536 個檔案,每個 4,096 bytes,合計 268.4 MB。從德國傳到美國,往返延遲約 141 ms RTT。兩台 VM 都有 4 個 vCPU 與 8 GB RAM。所有方法都使用 Btrfs loop volume,事先讀取來源資料,接收端從空白開始,不啟用壓縮。每種設定以打亂的順序測五次。速度以有效檔案位元組數,除以接收端檔案可用為止的時間計算;之後才做 sync 與 SHA-256 驗證。所有完成的複製都通過驗證。

先看現成工具,每種使用一條資料連線。完成傳輸的速度取五次測試的中位數:

方法傳輸速度(MB/s)
OpenSSH SFTP<0.299*
rsync(--whole-file)10.65
tar 串流經由 SSH 傳送10.05
Btrfs 完整快照傳送10.84
完整原始磁碟映像複製1.71†

SFTP 五次都達到 15 分鐘的時間上限;表中的數字是完成整批傳輸的速度上界。†原始映像實際傳送的資料量是有效檔案資料的八倍。工具的全部觀測結果與計時細節(英文)。

在這個 RTT 下,每個檔案若多等一次網路往返,合計就會多出 2.6 小時。OpenSSH 9.6 的遞迴 SFTP 客戶端依序處理各個檔案,流水線只用在單一檔案內部。Tar 把封裝串流透過 SSH 送給另一個 tar 程式,接收端邊收邊解開。Rsync 本來就有跨檔流水線。打包與流水線都能讓後面的檔案在前面的檔案完成前開始傳送。不過,這組現成工具的測量也包含其他實作差異。

Btrfs 完整 send 以串流傳送檔案資料與檔案系統操作。原始映像複製則搬動整個 2.15 GB 映像,連未使用空間也一起傳,只為交付 268.4 MB 的檔案。增量快照與變更區塊複寫需要用資料更新的情境測試;這裡只測完整複製。

另一批測試使用 Rust 程式,在 Linux TCP/TLS/yamux 與 Quinn QUIC 之間共用檔案 I/O 程式碼。一種模式允許最多 4,096 條檔案串流同時進行,另一種把紀錄打包成一條連續串流。兩者都能跨越檔案邊界持續傳送,不必等每個檔案完成。

單一連線的傳輸速度(MB/s):

檔案處理方式TCP + CUBICTCP + BBRQUIC + CUBICQUIC + BBR
跨檔流水線16.9920.046.5828.41
串流打包20.9019.096.9129.26

五次測試的中位數。

跨檔流水線與串流打包,在 TCP 或 QUIC 搭配 CUBIC 或 BBR 時的傳輸速度比較,單位為 MB/s。 開啟原尺寸圖表
圓點保留每一次觀測,包括較慢的結果。

把 CUBIC 換成 BBR,打包的 QUIC 從 6.91 升到 29.26 MB/s。同樣的變動在 TCP 上,卻是從 20.90 變成 19.09 MB/s。更換壅塞控制器後,TCP 與 QUIC 的快慢排名反轉了;Linux 與 Quinn 使用的是各自的控制器實作。

改用八條獨立的 BBR 連線後,打包小檔的速度達到 TCP 38.04 MB/s、QUIC 36.83 MB/s。這也同時增加了讀取與寫入的並行度。大檔案仍然快得多:

小檔案與大檔案使用一條或八條連線時的傳輸速度,單位為 MB/s。 開啟原尺寸圖表
總量同樣是 268.4 MB。大檔對照組使用一個檔案搭配一條連線,或八個等大的檔案搭配八條連線。

較早的工具測試,曾因另一個工作負載的 SSH 失敗而中斷,之後接續完成;80 次 Rust 測試則全程沒有中斷。這兩台共用 VM 出現過 UDP 緩衝區錯誤,以及偶發的 CPU steal,也就是虛擬機等待宿主機分配 CPU 的時間。兩批測試的實作與計時範圍也不同,不能把它們當成只改變傳輸協定的比較。設定與稽核細節(英文)。

我會先檢查,傳送端是否會在檔案邊界停下來等待,再測壅塞控制器。Tar、rsync 的流水線與自訂跨檔流水線,都在解決第一個問題。在這次 Quinn 的傳輸路徑上,跨檔連續傳送加上 BBR 的效果很好。TCP 沒有得到相同的 BBR 效益。光看協定名稱或複寫所在的層級,無法知道這兩件事是否做好了。若要逐步診斷自己的資料夾,請見大量小檔案傳輸為什麼很慢?原因與加速方法。

我參與 WarpSend 的開發,所以很在意這些細節。這個實驗沒有使用 WarpSend 的產品程式碼。

工具測試結果(英文) · 全部 80 筆 Rust 觀測(英文) · 測試程式與方法(英文)