WSL 2 效能更新:Virtiofs 的單一裝置 SWIOTLB 池

WSL 2 透過引入單一裝置 DMA 池,正在為跨作業系統的檔案存取提供顯著的效能提升。這項變更已於 2026 年 5 月透過 PR #40654 合併,消除了 virtiofs 路徑中的主要競爭點,特別造福了那些在 Linux 環境中建置位於 Windows 磁碟機上的專案的使用者。

DMA 層優化

WSL 2 中的跨作業系統檔案 I/O 使用了依賴於 bounce buffers(彈跳緩衝區)的 DMA(直接記憶體存取)層,這些緩衝區是硬體可以直接定址的 4 GB 邊界以下的保留記憶體區域。在 Linux 核心中,這被稱為 SWIOTLB 池。

先前,WSL 2 工作階段中的所有 virtio 裝置都共用單一的全域 SWIOTLB 池。這意味著 /mnt/c 的 virtiofs 掛載、/mnt/d 的掛載以及 virtio 網路卡都會競爭相同的緩衝區,在進行大量 I/O 操作時造成了瓶頸。

為了達成此目標,PR #40654 為每個 virtio 裝置提供了專屬的 DMA 池。核心現在會在開機時分配一個 4 GB 以下的連續實體範圍,並透過 sysfs(/sys/bus/vmbus/drivers/hv_pci/swiotlb_baseswiotlb_size)發布其位址。接著,WSL 服務會在裝置建立期間注入單一裝置的 swiotlb= 選項,從而消除共享隊列的競爭。

WSL 檔案系統存取演進史

為了理解這項更新的影響,有必要追蹤用於跨作業系統存取的傳輸協定演進過程:

  • WSL 1 (2016): 使用 DrvFs,這是 Windows NT 核心中的自定義檔案系統驅動程式。由於它缺乏 VM 邊界,在 /mnt/c 上的檔案操作幾乎是直接到達 NTFS,為檔案密集型工作負載提供了良好的效能。
  • WSL 2 (2019): 在 Hyper-V VM 中引入了完整的 Linux 核心。這提供了更好的 syscall 相容性,但引入了 VM 邊界。最初的跨作業系統存取是透過 Hyper-V socket 上的 Plan 9 (9P) 檔案伺服器來處理的。然而,9P 帶有協定開銷,因為操作受限於訊息大小參數 (msize=65536)。
  • Virtiofs (2021): 作為實驗性選用功能引入。Virtiofs 使用 VirtIO 傳輸來進行共享記憶體檔案存取,與 9P 相比,顯著減少了序列化開銷。

需求與實作

為了利用這些效能增益,使用者必須符合以下技術需求:

  • Kernel Version: Microsoft.WSL.Kernel 6.18.26.3-1 或更新版本。
  • WSL 2 DeviceHost: 版本 1.2.29-0。
  • Configuration:.wslconfig 檔案的 [wsl2] 區段中設定 virtiofs=true
  • System Resources: 維持 WSL 2 工作階段的 RAM 在 1 GB 以上,因為 SWIOTLB 池至少需要 64 MB 的餘裕空間。

使用者可以使用指令 wsl.exe --update --pre-release 來更新核心。

社群觀點與權衡

雖然這項更新解決了一個關鍵瓶頸,但社群討論強調了使用者對 WSL 2 與原生 Linux 之間效能差距的長期挫折感。

"WSL 單槍匹馬地阻止了許多開發者轉向 Windows 的浪潮,但 WSL 原生檔案系統效能讓開發者在第一次進入 Linux 時,能感受到那種神奇的體驗,看到檔案系統並非一團糟。"

一些開發者指出,效能差異在歷史上一直將他們推向原生 Linux 或 macOS。其他人則建議,最有效避免這些瓶頸的方法是將專案檔案保留在獨立的 EXT4 磁碟區,並將其掛載到 Windows 下,而不是在 /mnt/c 邊界進行操作。

儘管有這些優化,virtiofs 仍是一項選用功能,且跨作業系統存取的預設傳輸方式仍是透過 Hyper-V socket 上的 Plan 9。

Sources