为什么 Web 服务器在 WSL 中比在 VMware 中慢 2-3 倍? (相同的 Docker 堆栈)
Why is a web server 2-3x slower in WSL than in VMware? (same Docker stack)
我有一个 docker 撰写设置,包括:
- wordpress:php8.1
- mariadb:最新
- traefik:v2.7
为了排除 Windows 网络差异,这是来自内部的基准 运行:
curl --resolve example.com:443:172.18.0.3 --write-out '%{time_total}\n' --output /dev/null https://example.com
其中example.com是我自定义的域名,IP是traefik容器当前的IP。我是 运行 通过 SSH 进入 VMware 的命令,然后在输入 wsl
后从 PowerShell 进入。我按原样将项目从一个地方复制到另一个地方(感谢 Docker 的可移植性)。
对于 VMware 支持的实例,它始终 returns ~0.2s,而对于 WSL,它是 0.4-0.6s。 它代表 [=55] 的负载=] 本身包括 HTML 高性能 WP 站点的源代码,使用手工编码的主题,没有插件。在本地,静态版本似乎没有可测量的差异,或者非常轻微,两个系统上都在 10 毫秒以下。
其余配置:
- Windows 11 22H2 22610.1,WSL 2,VMware 16.1.0 build-17198959,Docker installed the same way 而不是 Docker 桌面。
- UFW 关闭。
- vmdk 和 vhdx 文件在同一个 SSD 上。
- 不跨文件系统使用 /mnt 文件:所有内容分别位于每个系统的主文件夹下。
- OS 在 WSL 中是 Ubuntu 20.04.4 LTS,在 VMware 中是 Ubuntu 21.10。我也在 WSL 和 WMware 中尝试了 Ubuntu 22.04 LTS,相同的数字。
- 我什至尝试过在 WSL 中使用 Nginx + PHP-WP 的 FPM 变体,在 VMware 中使用 OpenLiteSpeed,没有任何变化。
- 我所知道的唯一区别 是我必须
sudo update-alternatives --config iptables
并选择 /usr/sbin/iptables-legacy
才能使 Docker 在 WSL 中工作,这在 WMware 上我不需要这样做。
WSL2 中存在已知的网络瓶颈。
请参阅此 GitHub 问题以了解可能的解决方法:https://github.com/microsoft/WSL/issues/4901
一些对其他人有效的解决方案:
我的回答有几个注意事项:
- 我希望我有一个 解决方案 给你,但你的主要问题是 为什么,这应该回答。也许这里的数据会帮助我们找到解决方案。
- 我希望我是错的,我很可能是。我一直听说 WSL2 的性能“接近原生”。但是,您的经验以及我在下面的基准测试让我相信情况可能并非如此。
也就是说,我将报告我在调查此问题时得出的数据。
简短摘要——我的基准测试似乎显示出 Hyper-V 和 VMWare 之间的大量磁盘 IO 和内存性能差异,这可能解释了您的 WordPress 结果。
支持数据和研究
我从一个与您类似的测试场景开始,但我试图将其减少到尽可能多的 MRE:
配置
硬件:
- i9500
- 16GB 内存
- SSD
- 相当 fresh/recent 安装 Windows 11 Pro,启用 WSL2
- 全新安装 VMWare Workstation 16 播放器
虚拟化:
- 默认 VMWare 设置(2 CPUs,4GB RAM)
- 默认 WSL2 设置(6 CPUs,8GB RAM)
在 WSL2 和 VMWare 中:
- Ubuntu 服务器 20.04 guest/distribution
- Docker 都安装了(来自官方仓库,不是 Docker 桌面版)
ubuntu:latest
(22.04) Docker 图片
- MySQL 服务器 (MariaDB) 和 Sysbench 安装在 Ubuntu 22.04 Docker 容器中
请注意以下基准测试:
- 我在测试WSL2时关闭了VMWare,vice-versa.
- 我在两次测试之间没有重启 Windows 主机。但是,请注意,其中一些测试是 运行 多次,来自 VMWare 和 WSL2/Hyper-V,结果没有实质性差异,因此我认为重新启动不会显着改变结果。
基准测试
我开始对 CPU 和内存进行一些基本的 Sysbench 测试。这是在 Docker 容器内完成的。
一个简单的sysbench cpu --time=300 run
:
VMWare
WSL2
events/sec
1,250.97
1,252.89
# events
375,294.00
375,869.00
Latency
↪ Min
0.77
0.77
↪ Avg
0.80
0.80
↪ Max
31.40
4.07
↪ 95th percentile
0.87
0.86
几乎势均力敌。
sysbench memory run
:
VMWare
WSL2
Total operations
64,449,416.00
6,456,274.00
MiB transferred
62,938.88
6,304.96
Latency
↪ Min
0.00
0.00
↪ Avg
0.00
0.00
↪ Max
23.63
0.12
↪ 95th percentile
0.00
0.00
Ouch - WSL2 的 Docker 图像 运行ning 占用了 VMWare 内存带宽的大约 10%。我会说实话;在我在 table ;-) 中插入逗号分隔符之前很难发现这一点。乍一看,我觉得这两个不相上下
我决定直接跳到 MySQL 测试,同样使用 Sysbench,因为这可能会提供与您的 WordPress 使用情况最接近的匹配。这是通过以下方式完成的(在相应的 prepare
之后):
sysbench oltp_read_write.lua --mysql-user=root --time=300 --tables=10 --table-size=1000000 --range_selects=off --report-interval=1 --histogram run
我将跳过直方图和 second-by-second 结果(但如果它们对任何人有用,我会保存它们),但这里是摘要数据:
VMWare
WSL2
Queries performed
↪ Read
583,220
66,910
↪ Write
233,288
26,764
↪ Other
116,644
13,382
↪ Total
933,152
107,056
Transactions
58,322
6,691
Ignored errors
0
0
Reconnects
0
0
Latency
↪ Min
2.08
14.54
↪ Avg
5.14
44.83
↪ Max
71.67
193.75
↪ 95th Percentile
11.65
81.48
再次,哎哟——WSL2 的 MySQL 性能(至少在 Docker 中)的基准测试大约是 VMWare 的十分之一。您观察到的大部分性能差异可能都体现在这些结果中。
此时,我开始怀疑可以在管理程序级别以更通用 (IO) 的方式重现该问题,完全忽略 WSL2 和 Docker。 WSL2,当然,运行s 在(对用户隐藏的)Hyper-V 支持的 VM 中,即使它不需要完整的 Hyper-V 管理器。
我继续启用 Hyper-V 并在其中安装另一个 Ubuntu 20.04 客户机。然后我在 VMWare 和 Hyper-V guest Ubuntu OS.
中安装了 Sysbench
我然后运行一个磁盘IO比较:
sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 --histogram run
(当然先有一个对应的prepare
)
结果证实了怀疑:
VMWare Ubuntu Guest
Hyper-V Ubuntu Guest
File operations
↪ Reads/sec
2,847.07
258.37
↪ Writes/sec
1,898.05
172.25
↪ fsyncs/sec
6,074.06
551.20
Throughput
↪ MiB/sec Read
44.49
4.04
↪ MiB/sec Written
29.66
2.69
Latency
↪ Min
0.00
0.00
↪ Avg
0.09
1.02
↪ Max
329.88
82.77
↪ 95th Percentile
0.32
4.10
在此阶段需要注意的一件有趣的事情是,Sysbench 的 prepare
操作 比 Hyper-V 快 大约 30% (IIRC)。我没有捕获结果,因为 prepare
步骤不 应该 是基准测试的一部分。
但是,在阅读了您关于 unzip
在 WSL2 上速度更快的评论和基准测试结果后,我认为这可能存在关联。 VMWare 和 Hyper-V/WSL2 都使用动态调整大小的虚拟磁盘(有时称为“稀疏”)。主机上虚拟磁盘的大小 OS 基本上从接近 0 字节的文件开始,然后 增长 根据需要达到其最大大小。
可能是:
- Hyper-V在增大虚拟磁盘时具有性能优势。
- 或者在我们的测试中,VMWare 需要为这些操作增加磁盘但 Hyper-V/WSL2 磁盘已经有 e免费 space(来自之前删除的文件)可用。
我不能确切地说出我按照哪个顺序做事,唯一可以确定的方法是“shrink/compress”虚拟磁盘,然后再试一次。
总结
在我天真的眼中,至少在 Windows 的“专业”级别上,与 VMWare 相比,Hyper-V 似乎有一些严重的性能限制。
调整尝试和其他比较
我确实尝试过对 Hyper-V 系统进行一些调整,但我不是该领域的专家。无论如何,我们作为用户可以做的事情并不多,无法将任何 Hyper-V 调整扩展到 WSL2——Microsoft 必须做出大部分更改。
我确实尝试过将动态VHDX转换为固定VHDX,希望它能增加IO,但也没有做出实质性的改变。
我现在也试过了:
在 WSL2 中禁用交换
运行 使用更多线程的 Sysbench 测试
为 WSL2 设置固定的 12GB RAM 大小。
运行 我的主要桌面上的 WSL2 下的 sysbench,与我的测试系统的 SSD 相比,它具有更快的内存和 NVMe 驱动器。
- 内存速度显着提高 - Apples-to-oranges,但我的桌面内存数量与 lower-end 测试系统上的 VMWare 运行ning 相当。
- 但是,这对磁盘 IO 数量没有影响。它们仍处于与测试系统相同的 运行ge。
后续步骤
如果你能 运行 除了你的 WordPress 实例之外的一些类似的基准测试,那就太好了,因为你已经设置了两个环境。如果我们可以证实数据,我们应该至少向 WSL 团队报告。他们有望提供一些关于如何将 WSL2 调整为与 VMWare 接近对等的指导,或者与 Hyper-V 团队就此进行合作。
同样,Hyper-V 和 VMWare 之间的差异如此之大,这让我感到惊讶。我仍然很难相信我自己在基准测试中没有做错什么。
仔细研究 wsl
和经典 VM 并稍微刷新一下我的记忆后,我得出了一个理论,但我无法 证明它。
我希望这个答案无论如何都会有所帮助或吸引对这个问题有直接了解的人。
我在评论中问过我自己:
是否有可能 Hyper-V 只是配置为使用比 VMWare 少得多的 'raw power' 百分比? (即:与 windows 和 windows 获得几乎所有可用资源相比,微软给予 WSL 的优先级不高)还是 Hyper-V 性能(编码等)的更内在问题?
这来自我自己的理解,即 WSL 似乎更适合从 windows 访问 linux 商品,而不是 resource-intensive(包括网络速度)activity 喜欢托管网页。由于 WSL 的集成方式,直觉上认为它 运行 比典型的 VM 更快,但 VM 是完全可配置的,您几乎可以赋予它对资源的完全访问权限。
如果您查看 these 答案,您会发现它似乎并不是真的要替换 VM 本身。
所以我认为 WSL 可能没有针对这些任务进行配置,也没有足够的可配置性来改变它。
我认为微软针对 WSL 的主要用途是为 windows 用户提供一个动态工作流程,您可以在其中切换 Windows 和 Linux 商品(因为,恕我直言,Linux 在控制台商品方面比 Windows 好得多),但并不是要使 WSL 成为具有所有特性的 full-fledged VM。这也是有道理的,因为你为什么要制作一个网页并将其托管在 linux 环境中,而这个环境有与你不使用的 windows 环境共享资源的负担,并且是 'main' 那个吗?
我有一个 docker 撰写设置,包括:
- wordpress:php8.1
- mariadb:最新
- traefik:v2.7
为了排除 Windows 网络差异,这是来自内部的基准 运行:
curl --resolve example.com:443:172.18.0.3 --write-out '%{time_total}\n' --output /dev/null https://example.com
其中example.com是我自定义的域名,IP是traefik容器当前的IP。我是 运行 通过 SSH 进入 VMware 的命令,然后在输入 wsl
后从 PowerShell 进入。我按原样将项目从一个地方复制到另一个地方(感谢 Docker 的可移植性)。
对于 VMware 支持的实例,它始终 returns ~0.2s,而对于 WSL,它是 0.4-0.6s。 它代表 [=55] 的负载=] 本身包括 HTML 高性能 WP 站点的源代码,使用手工编码的主题,没有插件。在本地,静态版本似乎没有可测量的差异,或者非常轻微,两个系统上都在 10 毫秒以下。
其余配置:
- Windows 11 22H2 22610.1,WSL 2,VMware 16.1.0 build-17198959,Docker installed the same way 而不是 Docker 桌面。
- UFW 关闭。
- vmdk 和 vhdx 文件在同一个 SSD 上。
- 不跨文件系统使用 /mnt 文件:所有内容分别位于每个系统的主文件夹下。
- OS 在 WSL 中是 Ubuntu 20.04.4 LTS,在 VMware 中是 Ubuntu 21.10。我也在 WSL 和 WMware 中尝试了 Ubuntu 22.04 LTS,相同的数字。
- 我什至尝试过在 WSL 中使用 Nginx + PHP-WP 的 FPM 变体,在 VMware 中使用 OpenLiteSpeed,没有任何变化。
- 我所知道的唯一区别 是我必须
sudo update-alternatives --config iptables
并选择/usr/sbin/iptables-legacy
才能使 Docker 在 WSL 中工作,这在 WMware 上我不需要这样做。
WSL2 中存在已知的网络瓶颈。
请参阅此 GitHub 问题以了解可能的解决方法:https://github.com/microsoft/WSL/issues/4901
一些对其他人有效的解决方案:
我的回答有几个注意事项:
- 我希望我有一个 解决方案 给你,但你的主要问题是 为什么,这应该回答。也许这里的数据会帮助我们找到解决方案。
- 我希望我是错的,我很可能是。我一直听说 WSL2 的性能“接近原生”。但是,您的经验以及我在下面的基准测试让我相信情况可能并非如此。
也就是说,我将报告我在调查此问题时得出的数据。
简短摘要——我的基准测试似乎显示出 Hyper-V 和 VMWare 之间的大量磁盘 IO 和内存性能差异,这可能解释了您的 WordPress 结果。
支持数据和研究
我从一个与您类似的测试场景开始,但我试图将其减少到尽可能多的 MRE:
配置
硬件:
- i9500
- 16GB 内存
- SSD
- 相当 fresh/recent 安装 Windows 11 Pro,启用 WSL2
- 全新安装 VMWare Workstation 16 播放器
虚拟化:
- 默认 VMWare 设置(2 CPUs,4GB RAM)
- 默认 WSL2 设置(6 CPUs,8GB RAM)
在 WSL2 和 VMWare 中:
- Ubuntu 服务器 20.04 guest/distribution
- Docker 都安装了(来自官方仓库,不是 Docker 桌面版)
ubuntu:latest
(22.04) Docker 图片- MySQL 服务器 (MariaDB) 和 Sysbench 安装在 Ubuntu 22.04 Docker 容器中
请注意以下基准测试:
- 我在测试WSL2时关闭了VMWare,vice-versa.
- 我在两次测试之间没有重启 Windows 主机。但是,请注意,其中一些测试是 运行 多次,来自 VMWare 和 WSL2/Hyper-V,结果没有实质性差异,因此我认为重新启动不会显着改变结果。
基准测试
我开始对 CPU 和内存进行一些基本的 Sysbench 测试。这是在 Docker 容器内完成的。
一个简单的
sysbench cpu --time=300 run
:VMWare WSL2 events/sec 1,250.97 1,252.89 # events 375,294.00 375,869.00 Latency ↪ Min 0.77 0.77 ↪ Avg 0.80 0.80 ↪ Max 31.40 4.07 ↪ 95th percentile 0.87 0.86 几乎势均力敌。
sysbench memory run
:VMWare WSL2 Total operations 64,449,416.00 6,456,274.00 MiB transferred 62,938.88 6,304.96 Latency ↪ Min 0.00 0.00 ↪ Avg 0.00 0.00 ↪ Max 23.63 0.12 ↪ 95th percentile 0.00 0.00 Ouch - WSL2 的 Docker 图像 运行ning 占用了 VMWare 内存带宽的大约 10%。我会说实话;在我在 table ;-) 中插入逗号分隔符之前很难发现这一点。乍一看,我觉得这两个不相上下
我决定直接跳到 MySQL 测试,同样使用 Sysbench,因为这可能会提供与您的 WordPress 使用情况最接近的匹配。这是通过以下方式完成的(在相应的
prepare
之后):sysbench oltp_read_write.lua --mysql-user=root --time=300 --tables=10 --table-size=1000000 --range_selects=off --report-interval=1 --histogram run
我将跳过直方图和 second-by-second 结果(但如果它们对任何人有用,我会保存它们),但这里是摘要数据:
VMWare WSL2 Queries performed ↪ Read 583,220 66,910 ↪ Write 233,288 26,764 ↪ Other 116,644 13,382 ↪ Total 933,152 107,056 Transactions 58,322 6,691 Ignored errors 0 0 Reconnects 0 0 Latency ↪ Min 2.08 14.54 ↪ Avg 5.14 44.83 ↪ Max 71.67 193.75 ↪ 95th Percentile 11.65 81.48 再次,哎哟——WSL2 的 MySQL 性能(至少在 Docker 中)的基准测试大约是 VMWare 的十分之一。您观察到的大部分性能差异可能都体现在这些结果中。
此时,我开始怀疑可以在管理程序级别以更通用 (IO) 的方式重现该问题,完全忽略 WSL2 和 Docker。 WSL2,当然,运行s 在(对用户隐藏的)Hyper-V 支持的 VM 中,即使它不需要完整的 Hyper-V 管理器。
我继续启用 Hyper-V 并在其中安装另一个 Ubuntu 20.04 客户机。然后我在 VMWare 和 Hyper-V guest Ubuntu OS.
中安装了 Sysbench我然后运行一个磁盘IO比较:
sysbench fileio --file-total-size=15G --file-test-mode=rndrw --time=300 --max-requests=0 --histogram run
(当然先有一个对应的
prepare
)结果证实了怀疑:
VMWare Ubuntu Guest Hyper-V Ubuntu Guest File operations ↪ Reads/sec 2,847.07 258.37 ↪ Writes/sec 1,898.05 172.25 ↪ fsyncs/sec 6,074.06 551.20 Throughput ↪ MiB/sec Read 44.49 4.04 ↪ MiB/sec Written 29.66 2.69 Latency ↪ Min 0.00 0.00 ↪ Avg 0.09 1.02 ↪ Max 329.88 82.77 ↪ 95th Percentile 0.32 4.10 在此阶段需要注意的一件有趣的事情是,Sysbench 的
prepare
操作 比 Hyper-V 快 大约 30% (IIRC)。我没有捕获结果,因为prepare
步骤不 应该 是基准测试的一部分。但是,在阅读了您关于
unzip
在 WSL2 上速度更快的评论和基准测试结果后,我认为这可能存在关联。 VMWare 和 Hyper-V/WSL2 都使用动态调整大小的虚拟磁盘(有时称为“稀疏”)。主机上虚拟磁盘的大小 OS 基本上从接近 0 字节的文件开始,然后 增长 根据需要达到其最大大小。可能是:
- Hyper-V在增大虚拟磁盘时具有性能优势。
- 或者在我们的测试中,VMWare 需要为这些操作增加磁盘但 Hyper-V/WSL2 磁盘已经有 e免费 space(来自之前删除的文件)可用。
我不能确切地说出我按照哪个顺序做事,唯一可以确定的方法是“shrink/compress”虚拟磁盘,然后再试一次。
总结
在我天真的眼中,至少在 Windows 的“专业”级别上,与 VMWare 相比,Hyper-V 似乎有一些严重的性能限制。
调整尝试和其他比较
我确实尝试过对 Hyper-V 系统进行一些调整,但我不是该领域的专家。无论如何,我们作为用户可以做的事情并不多,无法将任何 Hyper-V 调整扩展到 WSL2——Microsoft 必须做出大部分更改。
我确实尝试过将动态VHDX转换为固定VHDX,希望它能增加IO,但也没有做出实质性的改变。
我现在也试过了:
在 WSL2 中禁用交换
运行 使用更多线程的 Sysbench 测试
为 WSL2 设置固定的 12GB RAM 大小。
运行 我的主要桌面上的 WSL2 下的 sysbench,与我的测试系统的 SSD 相比,它具有更快的内存和 NVMe 驱动器。
- 内存速度显着提高 - Apples-to-oranges,但我的桌面内存数量与 lower-end 测试系统上的 VMWare 运行ning 相当。
- 但是,这对磁盘 IO 数量没有影响。它们仍处于与测试系统相同的 运行ge。
后续步骤
如果你能 运行 除了你的 WordPress 实例之外的一些类似的基准测试,那就太好了,因为你已经设置了两个环境。如果我们可以证实数据,我们应该至少向 WSL 团队报告。他们有望提供一些关于如何将 WSL2 调整为与 VMWare 接近对等的指导,或者与 Hyper-V 团队就此进行合作。
同样,Hyper-V 和 VMWare 之间的差异如此之大,这让我感到惊讶。我仍然很难相信我自己在基准测试中没有做错什么。
仔细研究 wsl
和经典 VM 并稍微刷新一下我的记忆后,我得出了一个理论,但我无法 证明它。
我希望这个答案无论如何都会有所帮助或吸引对这个问题有直接了解的人。
我在评论中问过我自己:
是否有可能 Hyper-V 只是配置为使用比 VMWare 少得多的 'raw power' 百分比? (即:与 windows 和 windows 获得几乎所有可用资源相比,微软给予 WSL 的优先级不高)还是 Hyper-V 性能(编码等)的更内在问题?
这来自我自己的理解,即 WSL 似乎更适合从 windows 访问 linux 商品,而不是 resource-intensive(包括网络速度)activity 喜欢托管网页。由于 WSL 的集成方式,直觉上认为它 运行 比典型的 VM 更快,但 VM 是完全可配置的,您几乎可以赋予它对资源的完全访问权限。
如果您查看 these 答案,您会发现它似乎并不是真的要替换 VM 本身。
所以我认为 WSL 可能没有针对这些任务进行配置,也没有足够的可配置性来改变它。
我认为微软针对 WSL 的主要用途是为 windows 用户提供一个动态工作流程,您可以在其中切换 Windows 和 Linux 商品(因为,恕我直言,Linux 在控制台商品方面比 Windows 好得多),但并不是要使 WSL 成为具有所有特性的 full-fledged VM。这也是有道理的,因为你为什么要制作一个网页并将其托管在 linux 环境中,而这个环境有与你不使用的 windows 环境共享资源的负担,并且是 'main' 那个吗?