使用 48 GB RAM 的虚拟机运行几天后就会变得很慢,而使用 6 GB RAM 则不会

使用 48 GB RAM 的虚拟机运行几天后就会变得很慢,而使用 6 GB RAM 则不会

我已经处理这个问题好几个星期了,结果VM-guest 速度非常慢虚拟机运行几天后。

“缓慢”意味着 CPU 密集型操作比以前花费更多时间,而且这些操作似乎会随着时间的推移而累积。例如,重新加载 ClamD 签名通常需要约 35 秒,并且一个核心的负载为 100%,在没有任何其他负载的情况下,时间会增加到 1 分钟或更长时间,但如果有其他负载,则很容易需要 10 或 15 分钟。其他负载可能是某些 Web 应用程序的数据库查询,本身就已经在一个核心上产生了 100% 的负载。似乎没有问题,这两个操作只是以 CPU 能够达到的速度进行处理,而出现问题时,这两个 CPU 密集型任务本身会变慢,同时增加系统的整体负载。然后,每个其他类似的小操作htop也会产生不正常的高负载。此外,像 ClamD 这样在一个核心上通常负载为 100% 的进程现在显示为产生 150% 或更高的负载。理论上,正如 ClamAV 人员所说,这对于重新加载签名是不可能的,因为这根本不是多线程的。因此,似乎引入了一些开销,从而严重降低了整体系统性能。同时,VM 主机本身或同一主机上的其他 VM 都不会遇到任何性能问题。

这个问题以前在 UB 14.04 LTS 的客户操作系统上出现过,在全新安装(包括重新创建 VM 等)16.04 LTS 后也出现过。我想我能找到一个区别:如果虚拟机使用 48 GB 的 RAM,则问题会在运行几天后出现,如果仅使用 6 GB 的 RAM,则不会出现问题。我非常确定 RAM 数量确实是这两种情况下的唯一区别,测试的工作负载相同,并由使用 Jenkins 和 ClamD 签名更新的一些自动运行测试提供。至少 8 GB 的 RAM 也很可能不会出现问题,因为我有另一台具有这种内存的虚拟机没有出现问题,但我目前不知道 RAM 的上限是多少,直到问题发生。测试这个非常耗时,因为问题不是从一开始就存在的,而是在某个时间开始发生的。

我的服务器是 HP DL380 G7,配备 2 个 Intel Xeon X5675 @ 3,07 GHz 和 144 GB RAM,均匀分布在所有插槽和 RAM 插槽上。它运行 UB 16.04 LTS,在 ZFS 上托管虚拟机,测试的虚拟机有 8 个 vCPU 和 48 GB 或 6 GB 的 RAM。服务器的资源应该足以满足我的需求,前者使用的 G6 速度稍慢,RAM 稍少,但没有出现这些问题。而且,如果使用 48 GB RAM 则不会出现问题,虚拟机的行为也符合预期。我非常确定主机中没有交换或内存过量使用:

top - 11:49:38 up 28 days, 13:54,  1 user,  load average: 0.26, 0.33, 0.35
Tasks: 904 total,   1 running, 899 sleeping,   0 stopped,   4 zombie
%Cpu(s):  0.1 us,  0.5 sy,  0.0 ni, 99.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 14853158+total,  5032192 free, 13115475+used, 12344644 buff/cache
KiB Swap:  5852156 total,  5852144 free,       12 used. 11533812 avail Mem

我目前正在研究 NUMA 与“节点交错”,但我确信 NUMA 已启用。此外,从我读到的内容来看,性能影响可能在 20% 甚至 40% 左右,但不会严重到某些进程(如连接到数据库)完全超时。我也读到,在大多数情况下,人们应该根本不处理 NUMA 细节,而是保留操作系统默认值,让内核决定在哪里调度哪个线程等。无论如何,我不需要最后一点性能,只是目前一段时间后,速度变得令人无法接受。

$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22
node 0 size: 72477 MB
node 0 free: 14758 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23
node 1 size: 72572 MB
node 1 free: 11046 MB
node distances:
node  0   1
      0:  10  20
      1:  20  10
$ dmesg | grep -i numa
[    0.000000] NUMA: Node 0 [mem 0x00000000-0xdfffffff] + [mem 0x100000000-0x121fffffff] -> [mem 0x00000000-0x121fffffff]
[    0.000000] mempolicy: Enabling automatic NUMA balancing. Configure with numa_balancing= or the kernel.numa_balancing sysctl
$ sysctl -a | grep numa_
kernel.numa_balancing = 1
kernel.numa_balancing_scan_delay_ms = 1000
kernel.numa_balancing_scan_period_max_ms = 60000
kernel.numa_balancing_scan_period_min_ms = 1000
kernel.numa_balancing_scan_size_mb = 256

除了 NUMA,我还阅读了有关 Linux 中的大页面和 VirtualBox 的大页面的文章,但据我所知,不使用其中任何一个都会产生我所看到的如此巨大的负面影响。VirtualBox 谈到使用大页面可获得约 5% 的性能优势,虽然我的主机中没有明确设置大页面,但从我在 中看到的情况来看,它们是通过“透明大页面”使用和提供的/proc/vmstat

让我感到疑惑的是,48 GB 的 RAM 根本就不是那么多内存,我读过其他用户遇到的问题超过 128 GB 后已被分配,开发人员告诉他们1 TB 测试成功RAM。此外,最多 24 GB 的内存也同样适用,之前有问题的虚拟机使用这个内存没有任何问题,在撰写本文时,这个内存再次出现了问题。

您知道这里是什么原因造成这个问题吗?

答案1

当客户机在 NUMA 机器上使用大量内存时,就会发生这种情况。KSM 可能会合并不同虚拟机的类似内存页面,这些页面位于不同的 NUMA 内存区域,从而导致受影响的进程运行缓慢。

禁用 KSM merge_across_nodes:

echo 2 > /sys/kernel/mm/ksm/run && sleep 300 && cat /sys/kernel/mm/ksm/pages_shared

如果没有共享页面:

echo 0 > /sys/kernel/mm/ksm/merge_across_nodes && echo 1 > /sys/kernel/mm/ksm/run

确保在 /etc/sysctl.d 中设置 merge_across_nodes 以在重启后继续保持。

答案2

我看到的行为非常符合以下情况Linux 内核讨论的问题

内存管理性能倒退的决斗

尽管它主要谈论的是交换,补丁修复者这也只会导致 CPU 负载过重:

vfio 是一个很好的测试,因为通过固定所有内存,它可以避免交换,并且回收只浪费 CPU,基于 memhog 的测试会产生交换风暴,并且可能会显示更大的 stddev。

有一件事我不确定,那就是影响,Transparent Huge Pages因为虽然在我的系统中默认启用了它们,但 VirtualBox 似乎并不使用它们,而且它们似乎是针对操作系统设置而选择的:

$ cat /sys/kernel/mm/transparent_hugepage/enabled
always [madvise] never
$ cat /sys/kernel/mm/transparent_hugepage/defrag
always defer defer+madvise [madvise] never

其余一切都与我所看到的完全吻合。

相关内容