Еволюція Zen: що змінюється між поколіннями і що ви справді відчуваєте

Було корисно?

Ви не «відчуваєте» нове покоління CPU тому, що скріншот бенчмарка став гарнішим. Ви відчуваєте його тоді, коли p99 перестає стрибати о 10:03 щодня, коли вузли зберігання перестають відставати при scrub, коли рахунок за електроенергію припиняє рости швидше за кількість співробітників, і коли ваш канал інцидентів знову стає нудним.

Оновлення Zen — від Zen 1 до Zen 4 і варіанту Zen 4c — сповнені змін, які не видно на маркетингових слайдах, але болюче очевидні в продакшені. Це практичний огляд: що фактично змінюється між поколіннями, як це проявляється в реальних системах і як довести це командами команд, а не відчуттями.

Що ви справді відчуваєте: зміни, що впливають на продакшн

Більшість команд купують CPU так само, як купують парасольки: за тим, наскільки вони намочилися минулого разу. Це зрозуміло, але веде до неправильних очікувань. Між поколіннями Zen зміни, які ви відчуваєте, групуються в п’ять категорій:

1) Поведінка хвостової латентності змінюється

Zen — це не просто «більше IPC». Змінюється розмітка кешу, змінюються комплекси ядер, швидкості fabric і контролери пам’яті. Ці речі змінюють форму розподілів латентності. Велике «відчуття» Zen 3 для багатьох латентнісно‑чутливих сервісів було в тому, що між’ядерна комунікація стала менш дивною, бо змістився кордон CCX (детальніше далі). Zen 4 часто відчувається як «те саме, але швидше», поки ви не помітите, що пам’ять і PCIe можуть стати новим «стелею».

2) Рухаються межі пропускної здатності (і вузькі місця теж)

На старіших платформах ви могли бути обмежені CPU. На новіших — без змін у коді — ви можете стати обмеженими пам’яттю або I/O. Коли приходить PCIe 5, канали зберігання можуть переміститися від «PCIe — ліміт» до «прошивка NVMe, налаштування IOMMU або IRQ affinity — ліміт». Оновлення показують, яка частина стеку найповільніше брешеться.

3) Щільність ядер змінює все в операціях

Більша кількість ядер — це не лише вища пропускна здатність. Це більше чутливості до NUMA, більше конфліктів за спільні кеші, більше рішень про маршрутизацію переривань і більше способів нашкодити собі наївним універсальним тюнінгом ядра. Різниця між «швидким CPU» і «швидкою системою» — це чи встигають ваші рішення з урахуванням топології.

4) Енергія та терміни перестають бути фоном

Продуктивність на ват — це те, де Zen тихо вбиває конкурентів у датацентрі. Але більш агресивний turbo і щільніші сокети роблять «охолодження» інженерним параметром, а не після думкою від відділу інфраструктури. Якщо ви колись бачили, як вузол тротлить під тривалим навантаженням і потім поводиться нормально в продакшені — ви зустріли цю проблему.

5) Зрілість прошивки та мікрокоду важать більше, ніж хочеться

Нові платформи виходять з «ранньою особистістю життя». З часом це покращується. Ваша задача — ставитися до BIOS, AGESA і мікрокоду як до продакшн-залежностей. Якщо це звучить дратівливо — так. Також: це дешевше, ніж простої.

Цитата, щоб тримати вас чесними, від Gene Kranz: «Failure is not an option.» Цю фразу часто повторюють; сприймайте її як парафразовану ідею про строгість під тиском, а не як слоган продуктивності.

Жарт №1: Оновлювати CPU, щоб виправити архітектурну проблему — це як купувати швидший принтер, щоб покращити свій почерк.

Факти та контекст, що пояснюють дивні місця

Ви прийматимете кращі рішення, якщо запам’ятаєте кілька конкретних фактів про те, як ми сюди дісталися:

  1. Zen (2017) був «скиданням» AMD після епохи Bulldozer, повернувши високі IPC‑ядра і знову вийшовши на серйозну серверну конкуренцію.
  2. EPYC “Naples” (Zen 1) використовував підхід MCM з кількома кристалами; топологія була потужною, але її легко було неправильно налаштувати для NUMA‑чутливих навантажень.
  3. Zen 2 (2019) перейшов на чиплети: обчислювальні чиплети на 7нм плюс I/O‑діє. Це розділення є фундаментальним для того, що ви відчуваєте пізніше (особливо поведінка пам’яті/I/O).
  4. Zen 3 (2020) реорганізував ядра та кеш у єдиний 8‑ядерний комплекс на CCD, зменшивши певні штрафи при між’ядерній комунікації.
  5. Zen 4 (2022) приніс DDR5 і PCIe 5 у мейнстрім EPYC‑платформи, змістивши межу вузьких місць і оголивши неякісні частини I/O‑ланцюга.
  6. Варіанти з 3D V‑Cache змінили розмову про тюнінг: можна купити кеш замість надії на покращення латентності пам’яті. Це компроміс, який варто кількісно оцінити.
  7. Мітгації безпеки (епоха Spectre і далі) змінили дефолти ядра та поведінку гіпервізорів; порівняння між поколіннями без урахування цих мітгацій часто є фантазією.
  8. Linux навчився топології з часом. Покращення планувальника і NUMA‑балансування означають, що «той самий софт, інше ядро» може виглядати як зміна покоління.
  9. Infinity Fabric і її зв’язок із частотою пам’яті були повторюваною темою; це впливає на міжкристальну латентність і пояснює, чому налаштування пам’яті — не проста галочка.

Zen по поколіннях: зміни, важливі для опсів

Я буду трішки несправедливий до маркетингових назв і зосереджуся на тому, що б’є вас о 2‑й ночі. «Відчуття» кожного покоління — це поєднання дизайну ядер, кешу, пам’яті, I/O і зрілості платформи.

Zen 1 / Zen+ (ера Naples): «Швидко, але топологія вдарить вас, якщо будете вважати її Intel»

Сервери на Zen 1 стали шоком для ринку: багато ядер, багато ліній, гарна продуктивність за долар. Вони також познайомили багато команд з реальністю NUMA. Naples міг поводитися як кілька машин, зʼєднаних болтами, якщо ви не були обережні з наповненням пам’яті та розміщенням процесів.

Що відчуваєте: непередбачувана хвостова латентність при міжсокетному або міжкристальному чаті, і навантаження, які масштабуются до певного моменту — а потім різко падають.

Що робити: вивчіть ваші NUMA‑вузли, зафіксуйте критичні сервіси, і припиніть думати, що «розподілити по всіх ядрах» завжди добре.

Zen 2 (Rome): «Чиплети, краще масштабування і менше сюрпризів — якщо не наситити пам’ять»

Zen 2 зробив чиплетну архітектуру мейнстрімом у серверах. I/O‑діє централізувало контроллери пам’яті і I/O. Це часто робило платформу простішою для розуміння, але також робило пропускну здатність пам’яті спільним ресурсом, який можна швидко витратити при високій кількості ядер.

Що відчуваєте: краща продуктивність на ядро і загалом плавніше масштабування; але пам’яті‑інтенсивні навантаження починають показувати «пропускна здатність — новий CPU».

Що робити: ставте канали пам’яті як ресурс першого рівня. «Більше DIMM» може бути рішенням щодо продуктивності, а не лише ємності.

Zen 3 (Milan): «Об’єднаний CCX: латентність перестає бути “таємничою” для багатьох навантажень»

Великим операційним плюсом Zen 3 було те, що всередині CCD ядра ділились єдиним L3‑кешем замість дрібніших CCX‑сегментів. Це зменшило певні штрафи для потоків, що ділили дані, але випадково опинилися на різних ядрах.

Що відчуваєте: покращення p99 для сервісів з великою кількістю спільного read‑mostly стану (кеші, таблиці маршрутизації, деякі JVM‑навчальні навантаження), і менше «чому перенесення процесу на інше ядро змінює латентність?»

Що робити: перегляньте старі правила pinning. Деякі хаки, потрібні на Zen 1/2, стають зайвими — або навіть шкідливими.

Zen 4 (Genoa): «DDR5 і PCIe 5 зміщують цілі; гучніша енергія, прошивка і тюнінг I/O»

Справжня історія Zen 4 — це платформа: DDR5, PCIe 5 і вищі кількості ядер. Якщо ви працюєте зі зберіганням, мережею або будь‑чим, що по суті «переміщує байти і не повинно чекати», ви це відчуєте.

Що відчуваєте: запас пропускної здатності і можливість консолідувати більше навантажень на сокет — поки обробка переривань, налаштування IOMMU або чутливість до латентності пам’яті не наздоженуть вас.

Що робити: закладіть час на тюнінг BIOS/прошивки і вирівнювання IRQ/NUMA. Очікуйте ранні «квірики» платформи. Плануйте вікна для патчів.

Zen 4c (варіанти з щільними ядрами): «Більше ядер, трохи інша поведінка на ядро; рішення планування важливі»

Варіанти з щільними ядрами створені для максимізації пропускної здатності на стійку та ват. «Відчуття» — ви можете упакувати більше роботи, але треба більш свідомо обирати, які сервіси туди ставити (орієнтовані на пропускну здатність, менш чутливі до латентності), а які — на високочастотні частини.

Що відчуваєте: велика пропускна здатність для паралельних задач, але деякі однопотокові або латентнісно‑чутливі компоненти можуть потребувати ізоляції або інших SKU.

Що робити: розділіть «шар латентності» та «шар пропускної здатності» в плануванні ємності. Не змішуйте їх лише через зручність.

Топологія, NUMA, CCD/CCX: де ховається продуктивність

Якщо ви хочете одну ментальну модель, що пояснює більшість «дивностей» Zen — ось вона: ваш CPU не є монолітом. Це район з обчислювальними острівцями, з’єднаними дорогами. Деякі дороги швидкі. Деякі дороги мають затори. Ваша задача — тримати балакучих сусідів поруч.

Що змінилося між поколіннями Zen

  • Zen 1/2: менші домени кешу означали більше промахів між доменами кеша для спільних робочих наборів, що проявлялося як стрибки латентності при зміні розміщення потоків.
  • Zen 3: єдиний L3 на CCD зменшив штраф за «два потоки ділять дані, але не ділять шматок кеша». Це практична, вимірювана зміна.
  • Zen 4: поліпшення платформи підвищують стелі, але зростає складність топології. Кількість ядер зростає, змінюються канали пам’яті, і в залежності від BIOS та SKU у вас може з’явитися більше NUMA‑вузлів.

Чому SRE мають піклуватися

Рішення щодо топології виявляються як:

  • дрейф p95/p99 латентності коли ядро або планувальник мігрує потоки між ядрами/NUMA‑вузлами.
  • нерівномірне використання CPU (один NUMA‑вузол гарячий, інші простоюють), бо локальність пам’яті визначає ефективну пропускну здатність.
  • схильність jitter зберігання коли IRQ потрапляють на зайняті ядра на «не тому» NUMA‑вузлі відносно PCIe‑пристрою.

Правило: якщо навантаження має спільний стан і вам важлива латентність, тримайте його в одному домені кешу або прийміть витрати і вимірюйте їх. Надія — це не план.

Пам’ять і I/O: пропускна здатність, латентність, PCIe і реальність зберігання

У продакшені CPU рідко «ламаться» від того, що вони занадто повільні. Вони «ламаються», коли чекають. Чекають на пам’ять. Чекають на блокування. Чекають на завершення I/O. Кожне покоління Zen змінює ці патерни очікування.

Пропускна здатність пам’яті: тихий прискорювач (і тихий обмежувач)

З ростом кількості ядер пропускна здатність на ядро може впасти, якщо канали пам’яті не зростають пропорційно або якщо ви недо‑заповнили DIMM. DDR5 у Zen 4 допомагає, але також спокушає людей ставити менше DIMM «бо ємність вистачає». Потім вам телефонують, коли компактації та паузи GC стають гіршими.

Латентність пам’яті: податок на промахи

Латентність формується швидкістю пам’яті, таймінгами, поведінкою контролера та тим, наскільки далеко ядро від пам’яті, приєднаної до відповідного NUMA‑вузла. Зміни кешу в Zen 3 зменшують, як часто ви платите цей податок для певних патернів. Zen 4 все ще може карати погана локальність — просто швидше.

PCIe: коли «більше ліній» ≠ «більше продуктивності»

PCIe 4 → PCIe 5 подвоює теоретичну пропускну здатність, і ви навряд чи отримаєте 2× у реальному житті, якщо решта стеку не встигне: прошивка NVMe, блок‑шар ядра, трансляція IOMMU, маршрутизація IRQ і доступність CPU для завершень. Інженери зберігання вчаться цьому рано: шина рідко є єдиною шиною.

Відчуття, специфічні для зберігання

  • Вища потенційна IOPS означає, що витрати CPU на обробку переривань NVMe можуть стати вузьким місцем раніше.
  • Потенціал швидшого відновлення/scrub реальний, але лише якщо потоки перевірки сум‑контрольних/стискування і пропускна здатність пам’яті не б’ються між собою.
  • Зближення мережі і зберігання (швидкі NIC + швидкі SSD) загнати вас в територію «вирівнювання IRQ і NUMA», хочете ви того чи ні.

Жарт №2: PCIe 5 чудовий — тепер ви можете переносити дані вдвічі швидше туди, де ваш додаток чекає на м’ютекс.

Віртуалізація і планувальники: секція «чому ця VM відчуває уповільнення?»

Еволюція платформи Zen змінює історію віртуалізації двома шляхами: топологією і мітгаціями. Гіпервізори і ядра стали кращими, ніж раніше, але вони все ще роблять дурниці, якщо ви не поясните, що таке «біля».

Розміщення VM і vNUMA: наближати обман до правди

Якщо VM думає, що має рівномірний доступ до пам’яті, а хост — мульти‑NUMA топологію, ви фактично просите гостя приймати погані рішення планування на великій швидкості. Pinning і vNUMA — це не «мікро‑оптимізації». Це спосіб зупинити трафік між вузлами пам’яті, який з’їдає вас.

Мітгації і мікрокод: порівняння продуктивності потребує контексту

Мітгації ядра можуть змінюватися між релізами ОС, і оновлення мікрокоду можуть змінювати поведінку. Коли хтось каже: «Zen 4 лише на 10% швидший за Zen 3 для нашого навантаження», ваше перше питання має бути: «Що змінилось у ядрі і прошивці, і ми вимірюємо те саме?»

Практичні завдання: команди, виводи, рішення (12+)

Ось частина, яку можна скопіювати у ваші ранбуки. Кожне завдання містить: команду, що означає її вивід, і рішення, яке з цього випливає. Це орієнтовано на Linux, бо більшість Zen‑серверів там живе.

Завдання 1: Визначити покоління CPU і stepping

cr0x@server:~$ lscpu | egrep 'Model name|CPU\(s\)|Socket|Thread|NUMA node\(s\)'
Model name:                           AMD EPYC 7B13 64-Core Processor
CPU(s):                               128
Socket(s):                            2
Thread(s) per core:                   2
NUMA node(s):                         8

Значення: Ви бачите рядок моделі (допомагає зіставити з поколінням Zen) і кількість NUMA‑вузлів (великий натяк на топологію).

Рішення: Якщо NUMA‑вузлів багато — плануйте роботу з розміщенням/прив’язкою, перш ніж звинувачувати додаток.

Завдання 2: Підтвердити NUMA‑топологію і відповідність CPU→вузол

cr0x@server:~$ numactl --hardware
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 64412 MB
node 0 free: 51230 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 64500 MB
node 1 free: 52110 MB
...

Значення: Які ядра належать якому NUMA‑вузлу і скільки пам’яті доступно в кожному вузлі.

Рішення: Для латентнісно‑чутливих сервісів зафіксуйте CPU і пам’ять до вузла, який має локальний доступ до NIC/NVMe.

Завдання 3: Перевірити швидкість пам’яті і заповнені канали (швидкий сигнал)

cr0x@server:~$ sudo dmidecode -t memory | egrep 'Locator:|Speed:|Configured Memory Speed:|Size:'
Locator: P0_DIMM_A1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s
Locator: P0_DIMM_B1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s

Значення: Чи працюєте ви на очікуваних швидкостях і чи встановлені DIMM.

Рішення: Якщо конфігурована швидкість нижча за очікувану — виправте налаштування BIOS або розміщення DIMM перед тим, як тюнити софт.

Завдання 4: Побачити, чи CPU‑bound ви, чи чекаєте на I/O

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

12:10:01 AM  CPU   %usr  %nice  %sys  %iowait  %irq  %soft  %steal  %idle
12:10:02 AM  all  62.11   0.00  8.40    0.25   0.10   1.20    0.00  27.94
12:10:02 AM    0  95.00   0.00  3.00    0.00   0.00   0.00    0.00   2.00
...

Значення: Високе %usr означає роботу CPU; високе %iowait — CPU чекає на I/O.

Рішення: Якщо iowait високий — припиніть «тюнити CPU» і перевірте сховище/мережу. Якщо одне CPU задіяне на 100% — підозрюйте irq affinity або один «гарячий» потік.

Завдання 5: Виявити тиск у черзі виконання (перенавантаження планувальника)

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
12  0      0 5210432  91232 1832448    0    0    12   144 9800 21000 71  9 20  0  0
18  0      0 5209120  91232 1832600    0    0     0   512 9950 24000 76 10 14  0  0

Значення: r — кількість runnable‑задач. Коли вона постійно вища за доступні ядра (або за групу ядер, яка вам важлива), ви переповнені.

Рішення: Якщо черга виконання висока і латентність погана — зменшіть консолідацію або зафіксуйте критичні навантаження подалі від шумних сусідів.

Завдання 6: Перевірити поведінку частоти і тротлінг

cr0x@server:~$ lscpu | egrep 'CPU max MHz|CPU MHz'
CPU MHz:                               2890.123
CPU max MHz:                           3650.0000

Значення: Поточна частота vs макс.

Рішення: Якщо CPU MHz значно нижчий під навантаженням — перевірте power caps і thermal throttling у BIOS/BMC; не витрачайте час на «оптимізацію коду» спочатку.

Завдання 7: Підтвердити політику cpufreq governor

cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
performance

Значення: Governor впливає на підйом частоти і усталене поведение.

Рішення: Для низьколатентних сервісів віддавайте перевагу performance (або настроєним профілям), якщо обмеження по енергії не виміряні й не явні.

Завдання 8: Перевірити поведінку NUMA‑балансування ядра

cr0x@server:~$ cat /proc/sys/kernel/numa_balancing
1

Значення: Автоматичне NUMA‑балансування може мігрувати пам’ять/сторінки для локальності, іноді викликаючи латентнісні джиттери.

Рішення: Якщо бачите періодичні стрибки латентності, що узгоджуються з міграціями — розгляньте відключення для зафіксованих робочих навантажень, але тестуйте — не копіюйте механічно.

Завдання 9: Перевірити фактичну локальність пам’яті процесу

cr0x@server:~$ pidof myservice
24819
cr0x@server:~$ numastat -p 24819
Per-node process memory usage (in MBs) for PID 24819 (myservice)
Node 0   Node 1   Node 2   Node 3   Node 4   Node 5   Node 6   Node 7   Total
-----    -----    -----    -----    -----    -----    -----    -----    -----
Anon     812.3     19.5      3.1      0.2      0.1      0.0      0.0      0.0   835.2
File      42.0      1.0      0.0      0.0      0.0      0.0      0.0      0.0    43.0

Значення: Більшість пам’яті на Node 0, з невеликими віддаленими виділеннями в інших вузлах.

Рішення: Якщо пам’ять розпорошена по вузлах — зафіксуйте numactl або systemd CPUAffinity/NUMAPolicy для передбачуваної латентності.

Завдання 10: Перевірити локальність PCIe‑пристрою (який NUMA‑вузол володіє пристроєм)

cr0x@server:~$ lspci -nn | egrep 'Non-Volatile|Ethernet'
41:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
c1:00.0 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6] [15b3:101b]
cr0x@server:~$ cat /sys/bus/pci/devices/0000:41:00.0/numa_node
2
cr0x@server:~$ cat /sys/bus/pci/devices/0000:c1:00.0/numa_node
6

Значення: NVMe ближче до NUMA‑вузла 2; NIC — до вузла 6.

Рішення: Розміщуйте потоки зберігання біля вузла 2, мережеві потоки — біля вузла 6, або прийміть штраф між‑fabric і виміряйте його.

Завдання 11: Перевірити розподіл IRQ (поширена проблема Zen «чому одне ядро плавиться?»)

cr0x@server:~$ grep -E 'nvme|mlx|eth' /proc/interrupts | head
  180:  9812234          0          0          0   PCI-MSI 524288-edge      nvme0q0
  181:        0          0          0          0   PCI-MSI 524289-edge      nvme0q1
  190:  5021132          0          0          0   PCI-MSI 532480-edge      mlx5_comp0

Значення: Якщо всі переривання потрапляють на CPU0 (перший стовпець) — це поганий знак, якщо ви не спеціально закріпили таке.

Рішення: Якщо переривання сконцентровані — увімкніть і відтонюйте irqbalance або вручну призначте IRQ на CPU, що локальні до NUMA‑вузла пристрою.

Завдання 12: Підтвердити чергу NVMe і поведінку латентності

cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

Device            r/s     w/s   rMB/s   wMB/s  rrqm/s  wrqm/s %rrqm %wrqm r_await w_await aqu-sz  %util
nvme0n1        2200.0  1800.0   350.0   280.0     0.0     0.0  0.00  0.00   0.40    0.55   2.10  78.00

Значення: await — латентність; aqu-sz показує глибину черги; %util — насичення.

Рішення: Якщо %util близький до 100 і await росте — сховище насичене. Якщо await низький, але додаток повільний — підозрюйте CPU/блокування/мережу.

Завдання 13: Подивитися, чи обмежує вас пропускна здатність пам’яті (швидко і грубо)

cr0x@server:~$ perf stat -a -e cycles,instructions,cache-misses,LLC-load-misses,task-clock -- sleep 5
 Performance counter stats for 'system wide':

   98,234,112,991      cycles
   73,120,443,210      instructions              #    0.74  insn per cycle
    1,223,110,992      cache-misses
      401,223,114      LLC-load-misses
       5,002.12 msec   task-clock

       5.000891981 seconds time elapsed

Значення: Низький IPC разом з великою кількістю LLC‑промахів часто вказує на затримки пам’яті (не завжди, але це сильний натяк).

Рішення: Якщо домінують затримки пам’яті — робіть локальність кеша пріоритетом, зменшуйте віддалений доступ до пам’яті і перевіряйте заповнення/швидкість DIMM перед тим, як ганятися за флагами компілятора.

Завдання 14: Перевірити міграції CPU (підказка про латентнісні джиттери)

cr0x@server:~$ perf stat -p 24819 -e context-switches,cpu-migrations -a -- sleep 10
 Performance counter stats for 'system wide':

       210,554      context-switches
        12,321      cpu-migrations

      10.004112343 seconds time elapsed

Значення: Висока кількість CPU‑міграцій може означати, що ваші потоки стрибають між ядрами/NUMA‑вузлами.

Рішення: Якщо p99 поганий і міграцій багато — розгляньте CPU affinity, cgroup cpusets або тюнінг планувальника. Не просто «збільшувати кількість реплік».

Завдання 15: Перевірити статус hugepages (важливо для VM і БД)

cr0x@server:~$ grep -E 'HugePages|Hugepagesize' /proc/meminfo
HugePages_Total:     8192
HugePages_Free:      7901
Hugepagesize:        2048 kB

Значення: Hugepages налаштовані і доступні.

Рішення: Якщо ви покладаєтесь на hugepages і вони вичерпуються — отримаєте стрибкоподібні латентності і тиск на TLB; відкоригуйте виділення або усуньте витік/фрагментацію.

Завдання 16: Перевірити KVM і прапори nested virtualization (хости хмари/VM)

cr0x@server:~$ lsmod | grep kvm
kvm_amd               155648  0
kvm                  1064960  1 kvm_amd
cr0x@server:~$ cat /sys/module/kvm_amd/parameters/nested
0

Значення: Чи ввімкнена nested virtualization на хості.

Рішення: Увімкнюйте лише якщо потрібно. Nested ускладнює продуктивність і відладку; «на всяк випадок» — це як збирати загадкові оверхеди.

Плейбук швидкої діагностики: швидко знайти вузьке місце

Це послідовність триажу, якою я користуюсь, коли хтось каже: «Ми оновились з Zen X до Zen Y і не стало швидше» або «Швидше, але латентність погіршилась». Не імпровізуйте. Запускайте плей.

Перше: підтвердити реальність платформи (5 хвилин)

  1. CPU + кількість NUMA (lscpu): чи на тій ви залізі, яку думаєте? Чи змінились налаштування BIOS і показник NUMA?
  2. Швидкість і наповнення пам’яті (dmidecode): чи працюєте ви на очікуваних MT/s? Чи неповні канали?
  3. Governor і частота (scaling_governor, lscpu): чи застрягли ви в політиці енергозбереження?

Друге: класифікувати вузьке місце (10 хвилин)

  1. CPU vs iowait (mpstat): високе user/system vs високе iowait.
  2. Тиск черги виконання (vmstat): чи переповнені ви?
  3. Підказка про затримки пам’яті (perf stat): низький IPC + багато LLC‑промахів вказує на пам’ять.

Третє: вирівнювання топології (15–30 хвилин)

  1. Локальність пам’яті процесу (numastat -p): чи процес здебільшого локальний?
  2. NUMA‑вузол пристрою (/sys/bus/pci/.../numa_node): чи NVMe/NIC поруч з ядрами, що виконують роботу?
  3. Розподіл переривань (/proc/interrupts): чи IRQ «плавлять» одне ядро?

Умова зупинки: коли ви знайдете клас вузького місця (CPU, пам’ять, I/O, топологія), припиняйте збирати випадкові метрики. Виконайте одну зміну, виміряйте і тільки потім рухайтесь далі.

Три корпоративні міні-історії (анонімізовані, правдоподібні і трішки болючі)

Міні‑історія 1: Інцидент від неправильної припущення

Компанія мігрувала флот API‑серверів з Zen 2 на Zen 4. Тести продуктивності були чудові: пропускна здатність зросла, середня латентність впала. Роллаут провели поступово. Через тиждень — інцидент: p99 стрибає кожні кілька хвилин, лише на новому флоті, лише під змішаним трафіком.

Он‑кол команда робила те, що робить кожен під тиском: дивилися на завантаження CPU. Воно було в нормі. Дивилися на GC — все добре. Дивилися на балансувальник навантаження — теж здавалось нормальним, мабуть, з приводу гордості.

Неправильне припущення було тонким: «NUMA тепер обробляється ядром». На старих хостах NIC і найзавантаженіші робочі потоки випадково були на одному NUMA‑вузлі через те, як шасі було підключено. На нових хостах NIC опинився на іншому вузлі. Сервіс був налаштований з CPU‑набором, що прив’язував воркерів до «перших» ядер — зручно, стабільно і тепер дуже далеко від NIC.

Кожен пакет робив зайву поїздку через fabric. При невеликому навантаженні це не грало ролі. Під навантаженням додаткова латентність і промахи кеша перетворилися на періодичну прірву, бо зайнятий вузол ставав ще завантаженішим і ядро починало мігрувати речі, щоб впоратися.

Виправлення було нудним: вирівняти CPU affinity воркерів з NUMA‑вузлом NIC і переконатися, що політика пам’яті відповідає. Стрибки зникли миттєво. Ніхто не хотів визнавати, що це «лише» топологія, але графіки не переймалися гордістю.

Міні‑історія 2: Оптимізація, що відбилася назад

Команда зберігання оновила метадані‑сервера з Zen 3 на Zen 4. Побачивши запас ресурсів, інженер підвищив паралельність: більше воркерів, глибші черги, більші батчі. Ідея — «використати всі ті ядра». Це спрацювало — поки не перестало.

Першим симптомом не була продуктивність; це була змінна поведінка. Латентність стала більш стрибкоподібною, а не просто повільнішою в середньому. Нічні роботи почали перекриватися з денними піками по‑іншому, ніж раніше. У очевидних метриках нічого не було «на максимумі».

Відбій — класичний: нова паралельність пересунула навантаження з CPU‑bound у memory‑bandwidth‑bound. Zen 4 змістив стелю, але патерн доступу навантаження — багато pointer chasing, багато промахів кеша — означав, що CPU в основному чекав. Додаткові потоки посилили конкуренцію і мелену кешу, і система витрачала більше часу на координацію ніж на корисну роботу.

Вони відкотили зміну паралельності й протестували. Пропускна здатність трохи впала, але p99 стабілізувався і перекриття технічного обслуговування перестало викликати видимі клієнтам болі. Потім зробили реальне виправлення: більш осмислене шардування «гарячих» метаданих і фіксація найбалакучіших потоків у щільнішу локальність.

Урок: більше ядер не означає, що слід сліпо підвищувати паралельність. Легко створити швидший вузький горлечко і назвати це апгрейдом.

Міні‑історія 3: Нудна але правильна практика, що врятувала ситуацію

Платформна команда мала звичку, яку інші команди дражнили: кожне нове покоління апаратури проходило через один і той самий чекліст приймання. Версія BIOS, рівень мікрокоду, версія ядра, політика governor, налаштування IOMMU і невеликий набір відтворюваних «smoke benchmarks». Це не було ефектним. За це не аплодували.

Під час rollout Zen 4 вони помітили невелику, але послідовну аномалію: один пакет вузлів мав нижчу стійну частоту під навантаженням і гірший p99 у smoke‑тестах. Не катастрофа. Просто «трохи не так». Різниця корелювала зі слабко відмінним BIOS‑профілем, що йшов з постачальника для того пулу.

Вони призупинили rollout тільки для тих вузлів, виправили BIOS‑профіль і відновили. За два тижні інша команда виявила, що їхні вузли тротлять під пиковими батч‑роботами — бо вони не стандартизували прошивки і вважали дефолти прийнятними.

Платформна команда не виглядала героїчно в моменті. Але й не мала аварії. Їхня практика була нудною — і в цьому суть.

Поширені помилки: симптоми → корінь → виправлення

Це секція, яку ви вставляєте в ticket інциденту. Конкретні симптоми, ймовірні корені і виправлення, що реально змінюють результат.

1) Симптом: p99 гірший після оновлення, середня латентність краща

Корінь: невідповідність топології (потоки далеко від NIC/NVMe), збільшені міграції CPU або побічні ефекти NUMA‑балансування на системі з великою кількістю ядер.

Виправлення: Перевірте NUMA‑вузол пристрою і зафіксуйте потоки сервісу відповідно; перевірте локальність пам’яті за допомогою numastat; зменште міграції за допомогою affinity/cpuset; розгляньте відключення NUMA‑балансування для зафіксованих сервісів.

2) Симптом: NVMe‑бенчмарки покращились, але I/O додатка — ні

Корінь: додаток CPU‑bound у обробці syscall/interrupt/completion; IRQ зосереджені на одному ядрі; накладні витрати IOMMU/remapping; неоптимальні налаштування черг.

Виправлення: Перевірте /proc/interrupts; розподіліть IRQ; налаштуйте черги; виміряйте використання CPU у softirq; зафіксуйте I/O‑потоки локально до пристрою.

3) Симптом: Одне ядро загіповано на 100% sys, інші простіють

Корінь: IRQ affinity прив’язана до одного CPU (або irqbalance вимкнено), або є один гарячий ядровий потік.

Виправлення: Увімкніть irqbalance або вручну встановіть IRQ affinity; перевірте через /proc/interrupts і знову перевірте під навантаженням.

4) Симптом: Пропускна здатність масштабується до N потоків, а потім застопорюється

Корінь: насичення пропускної здатності пам’яті, контенція за блокуваннями або домінування трафіку між NUMA‑вузлами.

Виправлення: Використовуйте perf stat для пошуку stall‑ів; зменшіть віддалений доступ до пам’яті; шардуйте блокування; застосуйте структури даних дружні до кеша; не додавайте потоки лише так.

5) Симптом: «Нові CPU повільніші» на хості VM

Корінь: oversubscription vCPU, неправильний vNUMA, мітгації включені інакше, або зміни політики живлення хоста.

Виправлення: Перевірте чергу виконання і steal time; вирівняйте vNUMA з фізичною топологією; забезпечте узгоджені політики ядра/мікрокоду; встановіть governor.

6) Симптом: Відновлення/rebuild/scrub повільніше на нових вузлах

Корінь: потоки контрольних сум/стискування плануються далеко від дисків; контенція за пропускною здатністю пам’яті з сусідніми сервісами; неповне заповнення каналів пам’яті.

Виправлення: Розміщуйте воркери зберігання біля NVMe‑NUMA‑вузла; резервуйте ядра; правильно заповніть канали пам’яті; виміряйте пропускну здатність і stall‑и CPU.

7) Симптом: Випадкові стрибки латентності кожні кілька хвилин

Корінь: фонові роботи ядра (міграції NUMA‑сторінок, kswapd), осциляції thermal/power limit або періодичні роботи технічного обслуговування, що тепер конфліктують через інші характеристики продуктивності.

Виправлення: Корелюйте стрибки з міграціями (perf migrations, зміни numastat), перевірте частоти і тротлінг, перенесіть технічне обслуговування і ізолюйте навантаження.

Чеклісти / покроковий план

Чекліст планування оновлення (до покупки або перерозподілу флоту)

  1. Класифікуйте навантаження: шар латентності проти шару пропускної здатності. Розміщуйте їх на відповідних SKU (щільно‑ядерні частини не чарівні для одиничної‑поточної латентності).
  2. Інвентаризуйте вузькі місця сьогодні: CPU, пропускна здатність пам’яті, латентність пам’яті, I/O або контенція за блокуваннями. Спочатку використайте плейбук «Швидка діагностика».
  3. Визначте, що означає «краще»: p99, пропускна здатність при фіксованому p99, ват/запит, час відновлення, коефіцієнт консолідації. Оберіть два, не сім.
  4. Сплануйте управління прошивкою: версія BIOS/AGESA, політика мікрокоду, версія ядра. Ставте це як зафіксовані залежності з контрольованим rollout.
  5. Розробіть NUMA‑політику: будете pin‑ити? Використовувати cpusets? Дозволите планувальнику гуляти? Прийміть рішення свідомо.
  6. Підтвердьте правила наповнення пам’яті: канали заповнені для пропускної здатності, не лише для ємності.
  7. Змапте локальність пристроїв: де підключені NIC і NVMe? Переконайтесь, що шасі відповідає моделі розміщення навантажень.

Чекліст приймання (перший рік нової генерації)

  1. Запустіть lscpu і зафіксуйте модель CPU, NUMA‑вузли, max MHz.
  2. Запустіть dmidecode і підтвердьте, що конфігурована швидкість пам’яті відповідає очікуванням.
  3. Підтвердьте governor: performance (або вашу обрану політику).
  4. Перевірте розподіл IRQ під синтетичним навантаженням; виправте, якщо концентровано.
  5. Запустіть невеликий canary на рівні сервісу і порівняйте p50/p99, а не лише пропускну здатність.
  6. Запустіть smoke‑тести з мережі/зберігання і переконайтесь, що NUMA‑вузол пристрою відповідає стратегії розміщення потоків.

Операційний чекліст (поточний)

  1. Стандартизувати BIOS‑профілі і перевіряти відхилення.
  2. Відстежувати зміни ядра і мікрокоду як частину базових ліній продуктивності.
  3. Алертити про аномалії частот (тривалі годинникові частоти нижче очікуваних під навантаженням).
  4. Алертити про IRQ‑хотспоти (одне CPU отримує непропорційно багато переривань).
  5. Переглядати тиск консолідації: черги виконання, steal time і ефекти шумних сусідів.

Питання та відповіді

1) Чи є Zen 3 «великим» поколінням для латентнісно‑чутливих додатків?

Часто так — через зміну доменів кешу (єдиний L3 на CCD), що зменшує певні між‑ядерні штрафи. Але реальна відповідь залежить від того, скільки ваш додаток ділить дані між потоками і наскільки він чутливий до промахів кеша.

2) Чому мій p99 погіршився після переходу на новий CPU?

Тому що ви змінили топологію і поведінку, а не лише швидкість. Поширені причини: потоки тепер працюють далеко від NIC/NVMe; збільшились міграції CPU; NUMA‑балансування почало переміщувати сторінки; або ви потрапили в нове вузьке місце (пропускна здатність пам’яті, обробка IRQ).

3) Чи потрібно фіксувати процеси на сучасних системах Zen?

Якщо вам важлива передбачувана латентність — так, принаймні для критичних компонентів. Для пакетних/пропускних задач можна часто покластися на планувальник. Змішування обох без фіксації — це шлях до «швидко в середньому, жахливо, коли важливо».

4) Чи DDR5 завжди дає виграш?

Не автоматично. Вона підвищує стелі пропускної здатності, але латентність і конфігурація мають значення. Недозаповнені канали можуть стерти вигоду. Вимірюйте своїм навантаженням, а не надією.

5) Як зрозуміти, що я memory‑bound після апгрейду Zen?

Шукайте низький IPC із великою кількістю LLC‑промахів (perf stat) і масштабування, що перестає покращуватись при додаванні потоків. Потім підтвердьте, що пам’ять локальна (numastat) і що канали/швидкості DIMM налаштовані правильно.

6) Яка найпоширеніша «прихована» проблема на вузлах зберігання на нових поколіннях Zen?

Локальність переривань і розміщення CPU відносно NVMe. Залізо досить швидке, і помилки маршрутизації IRQ стають вузьким місцем.

7) Чи варто відключити NUMA‑балансування?

Для зафіксованих, латентнісно‑чутливих сервісів це може зменшити джиттер. Для загального багатокористувацького середовища воно може підвищити загальну ефективність. Правильна відповідь: протестуйте на вашому робочому навантаженні і порівняйте p99, а не лише середнє.

8) Чи змінюють покоління Zen поведінку ZFS?

ZFS залежить від CPU для контрольних сум і стиснення, від пропускної здатності пам’яті для ARC і навантажень з великою метаданою, і від I/O для латентності vdev. Нові Zen можуть прискорити CPU‑частину, але також роблять локальність IRQ і конфігурацію пам’яті важливішими.

9) Який практичний спосіб чесно порівняти покоління Zen?

Зафіксуйте: версію ядра, політику мітгацій, налаштування BIOS, заповнення/швидкості пам’яті, розміщення пристроїв і версію навантаження. Потім порівняйте при фіксованому p99 або при фіксованій пропускній здатності — не допускайте, щоб метрика сама змінилася.

Висновок: наступні кроки, які ви справді можете зробити

Еволюція Zen реальна, і ви її відчуваєте — але не завжди там, де вказує паспорт. Zen 3 зробив багато проблем латентності менш драматичними, змінивши домени кешу. Zen 4 зсунув стелю платформи завдяки DDR5 і PCIe 5, що означає: ваші старі «достатньо хороші» звички щодо I/O і топології тепер можуть стати вузьким місцем.

Наступні кроки, що швидко окуповуються:

  1. Запустіть плейбук «Швидка діагностика» на одному репрезентативному вузлі для кожного покоління. Не вгадуйте.
  2. Змапте локальність пристроїв (NIC/NVMe → NUMA‑вузол) і вирівняйте критичні потоки відповідно.
  3. Аудитуйте конфігурацію пам’яті: заповнені канали і конфігуровані швидкості, а не лише загальний об’єм GB.
  4. Перевірте розподіл IRQ під навантаженням і виправте хотспоти до того, як це стане «таємничим насиченням CPU».
  5. Стандартизувати прошивки і базові лінії ядра для флоту і відноситись до дрейфу як до ризику для продакшну.

Якщо ви зробите ці п’ять речей, оновлення Zen перестане бути стрибком віри і стане тим, чим має бути: інженерною зміною, яку можна осмислити, виміряти і розгорнути без сюрпризів.

← Попередня
Безпека zfs destroy: перевірки, що запобігають «Ой, не той датасет»
Наступна →
Debian 13 «Unable to locate package»: пастки репозиторіїв, архітектури та sources.list (та виправлення)

Залишити коментар