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_base 和 swiotlb_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 相比,显著降低了序列化开销。
要求与实现
要利用这些性能提升,用户必须满足以下技术要求:
- 内核版本: Microsoft.WSL.Kernel 6.18.26.3-1 或更高版本。
- WSL 2 DeviceHost: 版本 1.2.29-0。
- 配置: 在
.wslconfig文件的[wsl2]部分设置virtiofs=true。 - 系统资源: 保持 WSL 2 会话 RAM 在 1 GB 以上,因为 SWIOTLB 池至少需要 64 MB 的余量。
用户可以使用命令 wsl.exe --update --pre-release 来更新其内核。
社区观点与权衡
虽然此次更新解决了关键瓶颈,但社区讨论突出了开发者对 WSL 2 与原生 Linux 之间性能差距的长期挫败感。
"WSL singlehandedly stemmed much of tide of developers moving away from Windows, but WSL native filesystem performance gave devs that magical experience when they boot into Linux the first time and see that the filesystem doesn't have to be ass."
一些开发者指出,性能差异在历史上一直促使他们转向原生 Linux 或 macOS。其他人建议,最有效避免这些瓶颈的方法是将项目文件保存在单独的 EXT4 卷上并在 Windows 下挂载它,而不是跨越 /mnt/c 边界进行工作。
尽管进行了这些优化,virtiofs 仍是一项可选功能,且跨操作系统访问的默认传输方式仍是 Hyper-V socket 上的 Plan 9。