Уже несколько недель я решаю проблему, которая приводит к очень медленная ВМ-гость после того, как виртуальная машина проработала несколько дней.
«медленный» означает, что операции, связанные с ЦП, занимают больше времени, чем раньше, а также, что эти операции, похоже, накапливаются с течением времени. Например, перезагрузка сигнатур ClamD обычно занимает ~ 35 секунд и 100% на одном ядре, что увеличивается до 1 минуты и более без какой-либо другой нагрузки, но может легко занять 10 или 15 минут с другой загрузкой. Эта другая нагрузка может быть запросом к базе данных каким-либо веб-приложением, уже создающим 100% нагрузку на ядро само по себе. Кажется, что без проблемы обе операции просто выполняются с такой скоростью, на которую способен ЦП, в то время как с проблемой обе задачи, связанные с ЦП, становятся медленнее сами по себе и в то же время увеличивают общую нагрузку на систему. Каждая другая небольшая операция, такая как htop
или это также создает ненормально высокую нагрузку. Кроме того, такие процессы, как ClamD со 100% нагрузкой на одно ядро, обычно теперь отображаются как создающие 150% или более нагрузку. Что теоретически, как сказали люди из ClamAV, невозможно перезагрузить сигнатуры, потому что это просто не многопоточность. Таким образом, кажется, что вводятся некоторые накладные расходы, которые сильно снижают общую производительность системы. В то же время ни сам хост ВМ, ни другие ВМ на том же хосте не страдают от проблем с производительностью.
Это произошло с гостевой ОС UB 14.04 LTS в прошлом, а также с 16.04 LTS после новой новой установки, включая воссоздание виртуальной машины и т. Д. Думаю, мне удалось отследить это до одного отличия: Если виртуальная машина используется с 48 ГБ ОЗУ, проблема возникает через несколько дней работы, если она используется только с 6 ГБ ОЗУ, этого не происходит. Я очень уверен, что объем оперативной памяти действительно является единственной разницей в обоих случаях, тестируемая рабочая нагрузка одинакова и обеспечивается некоторыми автоматически запускаемыми тестами с использованием Jenkins и обновлениями сигнатур ClamD. Очень вероятно, что проблема не возникает, по крайней мере, с 8 ГБ ОЗУ, потому что у меня есть другая виртуальная машина с такой памятью, которая не показывает проблему, но в настоящее время я не знаю, каков верхний предел ОЗУ, пока возникает проблема. Проверка этого занимает довольно много времени, потому что проблема не существует с самого начала, она начинает происходить в какой-то момент.
Мой сервер - HP DL380 G7 с двумя процессорами Intel Xeon X5675 @ 3,07 ГГц и 144 ГБ оперативной памяти, равномерно распределенной по всем разъемам и слотам оперативной памяти. Он запускает UB 16.04 LTS, размещает виртуальные машины на ZFS, а протестированная виртуальная машина имеет 8 виртуальных ЦП и либо 48 ГБ ОЗУ, либо назначено 6. Ресурсов сервера должно быть более чем достаточно для моих нужд, использованный ранее G6 был немного медленнее, с меньшим объемом оперативной памяти и не проявлял этих проблем. И без проблем, возникающих с 48 ГБ ОЗУ, виртуальная машина также ведет себя должным образом. Я почти уверен, что на хосте нет подкачки или перегрузки памяти:
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 ГБ ОЗУ - это совсем не так много памяти, я читал, что другие пользователи сталкиваются только с проблемами после более 128 ГБ были назначены, и разработчики сообщили, успешно протестирован с 1 ТБ оперативной памяти. Кроме того, также работают объемы (до) 24 ГБ, которые ранее использовались проблемной виртуальной машиной без каких-либо проблем и снова используются на момент написания этой статьи.
Вы хоть представляете, что могло создать здесь проблему?
Это происходит, когда гость использует много памяти на машине 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
не забудьте установить merge_across_nodes в /etc/sysctl.d, чтобы он оставался после перезагрузки.
Поведение, которое я вижу, очень хорошо соответствует следующему проблема, обсуждаемая для ядра Linux:
Дуэльное снижение производительности управления памятью
Несмотря на то, что в основном речь идет о свопинге, автор исправления патча это также получило большую нагрузку на ЦП:
vfio - хороший тест, потому что, закрепляя всю память, он избегает подкачки и восстанавливает только трату ресурсов ЦП, тест на основе 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
Все остальное идеально соответствует тому, что я видел.