Якщо ви коли-небудь купували «швидші» CPU і спостерігали, що затримки в продакшні майже не змінилися, ви вже зіткнулися з кінцем ери GHz.
Дашборди виглядають самовдоволено: CPU менше ніж 40%, load average в нормі, але запити накопичуються, як багаж в аеропорту після снігопаду.
Це сучасна пастка продуктивності: частота перестала бути простим регулятором, а система ускладнилася так, що помилки в припущеннях караються.
Хороша новина — правила можна вивчити. Погана — їх не можна ігнорувати й сподіватися, що turbo boost врятує квартальні показники.
Чому «більше GHz» перестало працювати
Гонка тактової частоти завершилася з тієї ж причини, з якої закінчуються більшість гонок: це стало надто дорого і надто гаряче.
Масштабування частоти було золотою ерою, коли нічого не перекомпілюючи й не змінюючи архітектуру, можна було отримати приємний приріст щопокоління.
Та ера базувалася на негласній домовленості: зменшення транзисторів робило чипи і швидшими, і енергоефективнішими.
Домовленість зламалася.
Стіна потужності: фізика має свою думку
Динамічна потужність у CMOS часто апроксимується як P ≈ C × V² × f.
Можна махнути рукою на константи, але не на квадрати напруги.
Вищі частоти зазвичай вимагають вищої напруги, щоб зберегти часові запаси, і тоді потужність різко зростає.
Потужність перетворюється на тепло, тепло — на тротлінг, а тротлінг перетворює ваш блискучий «4.0 GHz» на практичний «3.1 GHz, якщо вентилятор не переграє».
Ось що таке стіна потужності: ви не можете нескінченно крутити частоту без перевищення теплового бюджету.
І в серверах тепловий бюджет не підлягає перемовинам. Шафа — це обігрівач кімнати, від якого залежить ваш дохід.
Dennard scaling перестав масштабуватись
Довгий час Dennard scaling робив транзистори меншими, швидшими й енергоефективнішими на одиницю площі.
Орієнтовно в середині 2000-х витік струму та інші ефекти зруйнували цю мрію.
Транзистори продовжували зменшуватися, але припиняли ставати пропорційно «дешевшими» в ватах.
Індустрія не перестала інновувати. Вона просто перестала давати вам безкоштовні пришвидшення для існуючого коду.
Стіна пам’яті: CPU біжить, RAM прогулюється
Навіть якби ви могли крутити частоту, багато серверної продуктивності блокується очікуванням.
Очікування пам’яті. Очікування промахів кеша. Очікування вводу/виводу. Очікування блокувань.
Ядра CPU стали достатньо швидкими, щоб завершувати інструкції героїчно—поки їм не потрібні дані, яких немає в кеші.
Затримки пам’яті покращувалися, але не такими ж темпами, як тактова тривалість CPU. Тому затримка, виміряна в тактах CPU, стала гіршою.
DRAM-доступ, який колись був «трохи повільний», став «вічністю» в циклах ядра.
Сучасні CPU борються з цим більшими кешами, кращими префетчерами, більше out-of-order виконанням і спекулятивними трюками.
Це працює—іноді. Але також ускладнює продуктивність так, що наївна «шопінг по GHz» схожий на купівлю спортивного автомобіля для міського трафіку.
Паралелізм і правильність: інша стіна
Коли частота перестала зростати, очевидним кроком стало «додати ядра».
Але «додати ядра» є безкоштовним тільки якщо ваше навантаження паралелізується, код потокобезпечний, і залежності не серіалізують усе.
Багато реальних систем обмежені кількома контендованими блокуваннями, однопотоковим циклом подій десь, або базою даних, яка чемно приймає ваші паралельні запити, а потім серіалізує їх на «гарячій» індексній сторінці.
Операційний переклад такий: апгрейд CPU не провалюється тому, що CPU слабкий. Він провалюється тому, що вузьке місце перемістилось—або ніколи не було CPU.
Якщо ви не вимірюєте, ви оптимізуватимете не те з упевненістю.
Одна цитата, яку варто тримати на стікері:
Парафраз ідеї (Edsger Dijkstra): Якщо ви не можете виміряти це, ви не можете суттєво покращити це.
Жарт №1: Гнатися за GHz у 2026—це як додавати більше кінських сил до авто, що стоїть за трактором—технічно вражає, емоційно — марно.
Цікаві факти та історичний контекст (коротко й по суті)
- Ранні 2000-ті: Споживчі та серверні CPU активно підвищували частоту; маркетинг концентрувався на GHz, бо це було просто і зрозуміло.
- Середина 2000-х: Dennard scaling ослаб; зріс витік потужності, і частота стала теплово дорогою, а не «просто інженерною».
- Урок епохи NetBurst: Деякі дизайни гналися за високими тактами з глибокими конвеєрами; добре на специфікаціях, менше добре в робочих циклах на інструкцію.
- Мульти-ядра стали мейнстримом: Індустрія переключилась з одноядерної швидкості на мульти-ядерні дизайни як прагматичний витрачач транзисторного бюджету.
- Ера turbo boost: Чипи почали підвищувати частоту опортуністично в межах теплового/потужного запасу; «base clock» став мінімальною юридичною величиною, а не обіцянкою досвіду.
- Адаптація Hyper-threading/SMT: Simultaneous multithreading збільшила пропускну здатність, коли виконавчі блоки були недовантажені, але не подвоїла продуктивність і іноді погіршувала хвостову латентність.
- Кеш став королем: Великі L3 кеші та розумні префетчери стали ключовими конкурентними фішками через вперту затримку пам’яті.
- NUMA всюди: Багатосокетні та chiplet-дизайни зробили локальність пам’яті проблемою продуктивності, яку можна випадково викликати неправильним планувальником або аллокатором.
- Бум спеціалізації: Векторні блоки, крипто-розширення, інструкції для стиснення та акселератори (GPU/NPUs) зросли, бо універсальні ядра стикнулись зі зменшенням віддачі.
Що замінило GHz: IPC, кеші, ядра та спеціалізація
IPC: інструкцій за цикл — нова гра престижу
GHz — це як метроном. IPC — це скільки музики ви граєте за такт.
Сучасна продуктивність CPU приблизно продуктивність ≈ частота × IPC, а потім її зменшують затримки: промахи кеша, неправильні передбачення переходів,
бульбашки в конвеєрі та очікування загальних ресурсів.
Два CPU з однаковою частотою можуть відрізнятися в IPC значно залежно від мікроархітектури, дизайну кеша, предикторів переходів
та набору інструкцій навантаження. Ось чому «однаковий GHz» не означає «однакова швидкість», і чому «вищий GHz» часто не еквівалентний «швидше».
Кеші: продуктивність, якої ви не бачите — поки не втратите
Попадання в кеш — це різниця між зайнятим ядром і ядром, що марить.
Багато інцидентів продуктивності в продакшні зводяться до збільшення робочого набору: нова фіча, новий індекс, новий JSON-блок, новий шар шифрування,
і раптом «гарячі» дані більше не вміщуються в кеш. Використання CPU може залишатися помірним, а пропускна здатність обвалюватися, бо CPU в основному чекає.
Ядра: пропускна здатність, не латентність (якщо вам не пощастить)
Додавання ядер допомагає, коли ваше навантаження має паралельну роботу і не серіалізується на загальній точці.
Це гра за пропускною здатністю: більше транзакцій за секунду, більше одночасних запитів, більше фонових завдань.
Якщо ваша проблема — латентність одиночного запиту, домінована одним потоком, більше ядер — плацебо.
В термінах операцій: масштабування за ядрами — це правильний хід для пакетної обробки, шардерних сервісів і безстанних горизонтально маштабованих endpoint’ів.
Це неправильний хід, коли моноліт має глобальне блокування, коли збирач сміття зупиняє світ, або коли база даних є вузьким місцем.
Векторизація та акселератори: спеціалізовані пришвидшення — справжні прирости
Коли універсальні ядра не можуть стати значно швидшими без ризику розплавлення, виробники інвестують у те, щоб виконувати конкретні завдання швидше:
SIMD/векторні інструкції для паралельної обробки даних, крипто-інструкції, стиснення та окремі акселератори.
Якщо ваше навантаження підходить — отримуєте величні вигоди.
Якщо ні — отримуєте чип, що «швидкий» в брошурі і «нормальний» у ваших метриках.
Планувальник і менеджер потужності: ваш CPU — це результат переговорів, а не абсолют
У 2026 році частота CPU — це політика. Turbo bins, обмеження потужності, тепловий запас, c-states, p-states і планування ядра
визначають, на яких тактах ви фактично працюєте. У щільному датацентрі ідентичні сервери можуть показувати різну продуктивність,
бо їхнє охолодження або подача живлення відрізняються тонко.
Реалії робочих навантажень: куди йде продуктивність
Латентність часто — це ланцюжок дрібних очікувань
Запит не «використовує CPU». Він проходить через черги, блокування, шляхи ядра, NIC-рінги, кеші файлової системи, сховища, буфери баз даних
і код у просторі користувача. Ваш p99 зазвичай не визначається середнім випадком; його визначають найгірші кілька взаємодій:
велика сторінкова затримка, пауза GC, ліміт cgroup через “шумного сусіда”, віддалений NUMA-доступ або збій у сховищі, що тягне потік в uninterruptible sleep.
Використання CPU — брехун, коли CPU чекає
Класична помилка: «CPU 30%, отже резерв є». Не якщо ці 30% — одне гаряче ядро, що завантажено, а решта — простає.
Не якщо у вас багато iowait.
Не якщо є контенція в черзі виконання.
Не якщо ви затримані через пам’ять.
Сховище та мережа: тихі співавтори «продуктивності CPU»
Як інженер зі зберігання, скажу прямо: ви не можете «апгрейдити CPU» щоб вирішити повільні fsync, синхронну реплікацію
або випадково випадково-важкі випадкові читання на невідповідному носії. CPU не виправить хвостову латентність від насиченої черги NVMe, і тим більше
не вирішить RAID-контролер, що тихо відновлює масив.
Аналогічно, проблеми з мережею проявляються як «CPU в порядку, але пропускна здатність упала». Тому що ваші потоки блокуються на сокетах,
ядро відкидає пакети або TLS-рукопотискання застрягають через нестачу ентропії (так, це ще трапляється).
Швидкий план діагностики: знайдіть вузьке місце без тижня зустрічей
По-перше: це час CPU, очікування CPU чи не CPU взагалі?
- Перевірте чергу виконання й насиченість CPU: якщо одне або кілька ядер забиті, ви CPU-bound навіть якщо «загальний CPU%» виглядає низьким.
- Перевірте iowait і заблоковані задачі: якщо потоки в uninterruptible sleep, ви чекаєте на I/O (сховище або мережеву ФС).
- Перевірте тиск пам’яті: великі fault’и і свопінг можуть зробити «швидкий CPU» повільним на практиці.
По-друге: якщо CPU-bound, це пропуск інструкцій чи пам’ятні затримки?
- Подивіться на сигнал(и), схожі на IPC: багато циклів з малою кількістю виконаних інструкцій вказує на стаґнацію; високі промахи кеша — звичайний підозрюваний.
- Перевірте переключення контексту й контенцію блокувань: багато переключень може означати накладні витрати планувальника або надто велику кількість потоків.
- Подивіться стеки процесів: знайдіть, куди йдуть цикли; не гадати.
По-третє: якщо I/O-bound, ідентифікуйте, яка черга заповнюється
- Затримка блочного пристрою: велике await/service time або глибокі черги вказують на насичення сховища або проблеми з пристроєм.
- Файлова система і writeback: брудні сторінки й тротлінг можуть зупиняти записувачів; fsync-важкі навантаження часті винуватці.
- Мережа: ретрансляції, дропи або насичення softirq CPU можуть імітувати «повільні сервери».
По-четверте: перевірте turbo/throttling і політику живлення (бо реальність)
Коли продуктивність «випадково» змінюється між ідентичними хостами, підозрюйте теплові або енергетичні обмеження.
Сучасні CPU ввічливі: вони захищають себе й бюджет вашого датацентру, тихо знижуючи частоти.
Практичні завдання: команди, що означає вивід і яке рішення прийняти
Це завдання, які я фактично виконую, коли хтось каже «нові CPU повільніші» або «нам потрібно більше GHz.»
Кожне завдання включає: команду, значення виводу та точку прийняття рішення. Використовуйте їх як чекліст, а не як ритуал.
Завдання 1: Перевірити реальну поведінку тактової частоти в реальному часі (не маркетингові чисельники)
cr0x@server:~$ lscpu | egrep 'Model name|CPU\(s\)|Thread|Core|Socket|MHz'
Model name: Intel(R) Xeon(R) CPU
CPU(s): 32
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 2
CPU MHz: 1298.742
Що це означає: CPU MHz — це знімок. Якщо він низький, поки машина зайнята, можливо ви в режимі енергозбереження, тротлінгу або під навантаженням, що часто спить.
Рішення: Якщо продуктивність погана, підтвердіть активні частоти під навантаженням (Завдання 2) і перевірте governor/обмеження живлення (Завдання 3/4).
Завдання 2: Спостерігайте за частотою по ядрах і навантаженням під час проблеми
cr0x@server:~$ sudo turbostat --quiet --interval 1
CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c6 CoreTmp
- 3120 38.50 4050 2500 12000 0 2.10 40.20 78
Що це означає: Bzy_MHz — ефективна частота при завантаженні; CoreTmp підказує про тепловий запас. Якщо Bzy_MHz нижче очікуваного turbo при високому Busy% і високих температурах — ймовірно, ви обмежені тепловим режимом.
Рішення: Якщо бачите низьке Bzy_MHz під навантаженням, перевірте обмеження живлення й охолодження. Не «оптимізуйте код», поки не переконаєтесь, що CPU не сам себе обмежує.
Завдання 3: Перевірити governor CPU (поширено в cloud-образах та ноутбуках, пристосованих під сервер)
cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
powersave
Що це означає: powersave може бути нормальним на сучасних intel_pstate системах, але в деяких конфігураціях воно обмежуватиме відзивчивість.
Рішення: Якщо латентність чутлива, встановіть відповідну політику (часто performance або налаштований профіль) і повторно протестуйте. Не робіть сліпих змін — виміряйте до/після.
Завдання 4: Перевірити індикатори термальних подій і тротлінгу
cr0x@server:~$ sudo dmesg -T | egrep -i 'thrott|thermal|powercap' | tail -n 5
[Mon Jan 8 10:22:11 2026] CPU0: Package temperature above threshold, cpu clock throttled
[Mon Jan 8 10:22:12 2026] CPU0: Core temperature/speed normal
Що це означає: Повідомлення ядра—це ваш тютюновий слід: ваш «GHz» було знижено.
Рішення: Виправте охолодження, потік повітря, монтаж радіатора, криву вентиляторів, BIOS-параметри живлення або щільність шаф. Не звинувачуйте компілятор.
Завдання 5: Визначити, чи ви насичені CPU або просто «трохи зайняті»
cr0x@server:~$ uptime
10:28:44 up 41 days, 3:02, 2 users, load average: 28.14, 27.90, 26.30
Що це означає: Load average близький або вище числа потоків CPU може вказувати на насичення, але він також рахує задачі в uninterruptible sleep (I/O wait).
Рішення: Поєднайте це з vmstat (Завдання 6), щоб відрізнити тиск на виконувані потоки від блокованого I/O.
Завдання 6: Швидкий огляд черги виконання, переключень контексту й iowait
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 812344 55284 932120 0 0 12 38 8200 9100 55 10 33 2 0
14 0 0 801120 55284 932992 0 0 10 22 8300 9500 58 9 31 2 0
2 6 0 794224 55284 931880 0 0 120 9800 4100 7000 12 6 40 42 0
Що це означає: r — runnable threads; b — blocked. Високі wa і високий b вказують на I/O-стали. Високий r з низьким id вказує на насичення CPU.
Рішення: Якщо заблоковано/багато I/O — переходьте до завдань по сховищу/мережі. Якщо CPU — профілюйте (Завдання 11/12).
Завдання 7: Визначити, чи одне ядро «прилипло» (брехня «CPU 30%»)
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server) 01/09/2026 _x86_64_ (32 CPU)
01:02:01 PM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
01:02:02 PM all 18.2 0.0 3.1 0.4 0.0 1.0 0.0 77.3
01:02:02 PM 7 98.5 0.0 1.2 0.0 0.0 0.0 0.0 0.3
Що це означає: CPU 7 завантажений. Загалом виглядає нормально; ваша латентність не дбає про «all».
Рішення: Знайдіть гарячий потік/процес. Розгляньте шардинг, усунення однопотокових вузьких місць або осмислене прив’язування (не случайне).
Завдання 8: Перевірити тиск пам’яті і великі fault’и (комбо «швидкий CPU, повільні page fault’и»)
cr0x@server:~$ sar -B 1 3
Linux 6.5.0 (server) 01/09/2026 _x86_64_ (32 CPU)
01:04:11 PM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s
01:04:12 PM 12.00 84.00 6200.00 0.00 10200.0 0.00 0.00
01:04:13 PM 18.00 1200.00 7100.00 180.00 9800.0 220.00 60.00
Що це означає: Сплеск majflt/s означає реальні сторінкові помилки з диска. Це руйнує хвостову латентність.
Рішення: Додайте пам’ять, зменшіть робочий набір, налаштуйте кеші або виправте деплой, що роздув використання пам’яті. Не купуйте вищі GHz, щоб «виправити» пейджинг.
Завдання 9: Перевірити NUMA локальність (віддалена пам’ять — «повільний CPU» в масці)
cr0x@server:~$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 128000 MB
node 0 free: 42000 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 128000 MB
node 1 free: 18000 MB
Що це означає: Два NUMA-вузли. Нерівномірність вільної пам’яті може підказувати про нерівномірні виділення або pinning.
Рішення: Якщо процес прив’язаний до CPU вузла 1, але виділяє пам’ять в основному на вузлі 0 — очікуйте віддалених читань. Використовуйте numastat (наступне завдання).
Завдання 10: Підтвердити, чи процес платить «податок віддаленої пам’яті»
cr0x@server:~$ pidof myservice
24188
cr0x@server:~$ numastat -p 24188 | head -n 8
Per-node process memory usage (in MBs) for PID 24188 (myservice)
Node 0 Node 1
Huge 0.00 0.00
Heap 18240.12 1024.55
Stack 8.00 2.00
Private 20110.33 1210.77
Що це означає: Велике виділення на вузлі 0. Якщо планувальник запускає потоки на вузлі 1 — ви виконуєте віддалі читання.
Рішення: Виправте CPU affinity, використайте інтерліювання усвідомлено або запускайте один інстанс на сокет. Часто це дає більше, ніж 200 MHz.
Завдання 11: Визначити топ-споживачів CPU і чи вони в користувацькому чи в ядровому просторі
cr0x@server:~$ top -b -n 1 | head -n 15
top - 13:08:21 up 41 days, 3:42, 2 users, load average: 28.14, 27.90, 26.30
Tasks: 412 total, 6 running, 406 sleeping, 0 stopped, 0 zombie
%Cpu(s): 61.2 us, 9.7 sy, 0.0 ni, 27.9 id, 0.9 wa, 0.0 hi, 0.3 si, 0.0 st
MiB Mem : 257996.0 total, 92124.3 free, 32110.7 used, 133761.0 buff/cache
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
24188 app 20 0 18.2g 6.1g 120m R 395.0 2.4 123:41.33 myservice
Що це означає: Сервіс використовує ~4 ядра CPU. Системний час—суттєвий; може це мережа, системні виклики, файлова система або контенція.
Рішення: Якщо sy високий — перевірте гарячі точки в ядрі (softirqs, syscalls) і розгляньте offload’и або батчинг. Якщо us високий — профілюйте користувацький код.
Завдання 12: Зразок куди йдуть CPU-цикли (perf top)
cr0x@server:~$ sudo perf top -p 24188
18.40% myservice myservice [.] parse_json_fast
11.22% myservice myservice [.] sha256_compress
7.10% libc.so.6 libc.so.6 [.] __memmove_avx_unaligned_erms
4.85% [kernel] [kernel] [k] tcp_recvmsg
Що це означає: Гарячі функції — парсинг JSON і хешування. Це обчислювальна робота; «більше GHz» може трохи допомогти, але вибір алгоритму та формату даних може дати набагато більше.
Рішення: Розгляньте зменшення накладних витрат JSON (бінарний формат, менше полів), увімкніть апаратне прискорення криптооперацій або винесіть хешування в спеціалізовану бібліотеку. Виміряйте вплив на p99.
Завдання 13: Збір підказок з апаратних лічильників (промахи кеша, цикли, інструкції)
cr0x@server:~$ sudo perf stat -p 24188 -e cycles,instructions,cache-references,cache-misses,branches,branch-misses -- sleep 10
Performance counter stats for process id '24188':
21,334,112,901 cycles
15,002,118,777 instructions # 0.70 insn per cycle
2,112,440,918 cache-references
388,004,112 cache-misses # 18.37% of all cache refs
3,122,114,662 branches
61,110,221 branch-misses # 1.96% of all branches
10.003022332 seconds time elapsed
Що це означає: IPC ~0.70 вказує на стаґнацію; відносно високий рівень промахів кеша. Ви не «занадто повільні в GHz», ви чекаєте на пам’ять.
Рішення: Сфокусуйтесь на локальності даних: зменшіть pointer-chasing, зменшіть об’єкти, покращіть батчинг або перебудуйте гарячі цикли. Розгляньте більші кеші або меншу кількість потоків, що шкодять кешу.
Завдання 14: Ідентифікувати затримки I/O і глибину черги на блочних пристроях
cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server) 01/09/2026 _x86_64_ (32 CPU)
Device r/s w/s rKB/s wKB/s await aqu-sz svctm %util
nvme0n1 120.0 2100.0 8400 98200 18.40 42.10 0.35 92.0
Що це означає: %util близько 100 і високі await/aqu-sz означають, що черга пристрою глибока й запити чекають. CPU буде виглядати «в порядку», поки застосунок блокується.
Рішення: Зменшіть синхронні записи, налаштуйте черги, розділіть шумні навантаження або масштабуйтесь по сховищу. Якщо ви бачите це, припиніть сперечатися про частоту CPU.
Завдання 15: Підтвердити тиск запису файлової системи (поширено при вибухових записах)
cr0x@server:~$ grep -E 'Dirty|Writeback' /proc/meminfo
Dirty: 1823456 kB
Writeback: 412800 kB
Що це означає: Високі Dirty/Writeback вказують на велику кількість очікуваних очищень. Якщо записувачі тротлінгуються — сплески латентності гарантовано.
Рішення: Перевірте, чи ваш додаток викликає fsync занадто часто, чи потрібні інші опції монтування, або чи варто перемістити логи на окремі пристрої.
Завдання 16: Знайти мережеві ретрансляції і дропи (бо «повільний CPU» іноді — TCP-біль)
cr0x@server:~$ netstat -s | egrep -i 'retransmit|segments retransm|listen|overflow|dropped' | head -n 10
12345 segments retransmitted
98 listen queue overflows
98 listen queue drops
Що це означає: Ретрансляції і переповнення listen-черги — отрута для латентності. Ваш CPU може бути простаючим, поки запити таймаутять і повторюються.
Рішення: Налаштуйте backlog, виправте втрату пакетів, масштабуйте фронтенди або відвантажте TLS. Не купуйте вищі такти, щоб компенсувати мережеві дропи.
Жарт №2: Якщо ваше рішення «додати 500 MHz», ви на крок від того, щоб звинуватити ретроградний Меркурій у втраті пакетів.
Три корпоративні міні-історії (анонімізовані, технічно правдоподібні та болісно знайомі)
Міні-історія 1: Інцидент через хибне припущення (GHz як доля)
Середня SaaS-компанія мігрувала latency-sensitive API з старих серверів на новіші. Презентація для закупівлі була чистою:
нове покоління, вищий рекламований turbo, більше ядер, «кращий у всьому». Команда очікувала зниження p95.
Натомість p95 погіршився—іноді суттєво—в години піку.
Перша реакція була передбачуваною: звинутити код. Утворився перфоманс «war room», і інженери почали пропонувати мікрооптимізації.
Тим часом SRE помітили дивну річ: найгірша латентність корелювала з підмножиною хостів, і ті хости мали трохи вищі вхідні температури.
Не критично — просто «трохи тепліше».
Вони запустили turbostat під час навантажувальних тестів і виявили, що ефективна частота при завантаженні була послідовно нижчою на теплих хостах.
CPU трималися в межах безпечних лімітів, понижуючи такти. Турбо з технічного опису був досяжний лише з достатнім тепловим запасом,
а розклад шаф змінився—щільніше обладнання, інший повітряний потік, ті ж припущення щодо охолодження.
Хибне припущення було не в тому, що «GHz важливі». Хибне припущення було в тому, що «GHz — це константа». У сучасних системах це змінна.
Вони виправили фізичну проблему: покращили потік повітря, перебалансували розташування в шафі і обережно відкоригували power caps в BIOS.
Лише тоді «швидші» CPU стали швидшими, і лише тоді профілювання коду стало сенсовним.
Тривалий урок був операційним: коли продуктивність регресує після оновлення апаратури, розглядайте середовище як першокласного підозрюваного.
Частота — це політика + фізика, а не число, яке ви маєте в кишені.
Міні-історія 2: Оптимізація, що відкотилась назад (більше потоків — менше пропускної здатності)
Команда пайплайна даних мала CPU-важкий enrichment-сервіс. Вони бачили завантаження CPU на 60% і вирішили, що є резерви.
Хтось збільшив пул робочих потоків з 16 до 64. Зміна швидко вийшла, бо «лише конфігурація».
У синтетичних тестах пропускна здатність покращилась. У продакшні ж з’явився жахливий сплеск p99 і загальна пропускна здатність впала в годину пік.
Симптоми були заплутаними: завантаження CPU зросло, але також і переключення контексту. Рівень промахів кеша піднявся.
Сервіс почав таймаутити виклики до даунстрім-залежності, що спричинило ретраї. Ретраї збільшили навантаження, що збільшило таймаути, що збільшило ретраї — класична петля зворотнього зв’язку, підсилена пулом потоків.
Профілювання показало, що гарячі шляхи коду були пам’яттєво-інтенсивні: парсинг, алокації об’єктів, хеш-таблиці та спільний LRU-кеш.
При 64 потоках робочий набір на ядро не вміщувався в кеш, й контенція на блокуваннях спільного кеша зросла.
CPU не був «недовикористаний» на 60%; він уже чекав на пам’ять і конкурував за спільні структури.
Виправлення не було в принципі «менше потоків»; воно полягало в «правильному розмірі конкурентності». Вони зупинились на меншому пулі,
розділили кеші на воркери, щоб зменшити контенцію, і налаштували поведінку аллокатора. Пропускна здатність покращилася, p99 стабілізувався.
Висновок: більше ядер і більше потоків — не стратегія продуктивності. Це множник для того, що вже є вашим вузьким місцем.
Якщо множити контенцію й шкідливе трясіння кеша — отримаєте інцидент продуктивності з відмінним використанням CPU.
Міні-історія 3: Нудна, але правильна практика, що врятувала день (базове профілювання і канарки)
Команда платформ великого підприємства запускала змішане навантаження на кластері: веб-трафік, фонова робота та кілька «тимчасово постійних» пакетних процесів.
У них було правило, яке дратувало розробників: кожна суттєва зміна апаратури або ядра вимагала пул канарок і захоплення базових показників.
Не тижневі бенчмарки — просто достатньо, щоб порівняти ключові лічильники й гістограми латентності.
Новий rollout ядра пішов у пул канарок. Через кілька годин канарки показали трохи вищий системний час і невелике збільшення хвостової латентності.
Нічого драматичного. Саме те, що ви б пропустили, якби дивилися лише середній CPU.
Але базова метрика включала perf stat counters для промахів кеша й переключень контексту, плюс iostat і мережеві ретрансляції.
Дані вказували на зміну поведінки планування і збільшення softirq під навантаженням.
Вони зупинили rollout, відтворили проблему в staging і звузили її до комбінації IRQ-affinity NIC і нового дефолту в енергоменеджменті.
Виправлення було банальним: налаштування IRQ-affinity і застосування tuned-профілю для цього класу навантаження.
Оскільки вони використовували канарки і базові виміри, «інцидент» ніколи не дійшов до клієнтів.
Жодних екстрених ролбеків, жодних звітів керівництву о першій ночі, жодної піци.
Практика була нудною. Але вона була правильною. Так виглядає надійність, коли її роблять свідомо.
Поширені помилки (симптом → корінь → виправлення)
1) Симптом: Загальний CPU низький, але p99 висока
Корінь: Одне ядро завантажене, однопотоковий вузький шлях або серіалізована секція (глобальне блокування, event loop, пауза GC).
Виправлення: Використайте mpstat -P ALL щоб знайти гарячі ядра, потім профілюйте відповідний процес/потік. Зменшіть серіалізацію, шардуйте роботу або винесіть важку роботу з request path.
2) Симптом: «Нові сервери повільніші» в підмножині хостів
Корінь: Тротлінг через тепло, обмеження потужності, різні налаштування BIOS або нерівномірне охолодження.
Виправлення: Підтвердіть ефективні busy MHz за допомогою turbostat, перевірте dmesg на теплові події, уніфікуйте BIOS-профілі і виправте потік повітря/щільність шаф.
3) Симптом: CPU помірний, але пропускна здатність падає під час сплесків записів
Корінь: Насичення черги сховища, fsync-шторм, тротлінг writeback або контенція під час відновлення RAID.
Виправлення: Використайте iostat -x, перевірте Dirty/Writeback, розділіть пристрої для логів, батчуйте fsync або забезпечте IOPS/латентність.
4) Симптом: Більше потоків зробило гірше
Корінь: Контенція, накладні перемикань контексту, трясіння кеша або підсилення даунстріму через ретраї/таймаути.
Виправлення: Виміряйте переключення контексту (vmstat), профілюйте блокування, обмежте конкурентність, розділіть спільні структури і впровадьте backpressure.
5) Симптом: CPU «випадково» стрибає в sys time
Корінь: Насичення softirq в мережі, велика кількість системних викликів, дропи пакетів що викликають ретрансляції, або накладні витрати стеку зберігання.
Виправлення: Перевірте sys% в top, ретрансляції в netstat -s, IRQ-affinity і розгляньте батчинг, offload’и або зменшення системних викликів на запит.
6) Симптом: Латентність погіршується після переходу на мульти-сокетні машини
Корінь: Віддалений NUMA-доступ через розміщення планувальника, дисбаланс у виділенні пам’яті або pinning контейнерів.
Виправлення: Використайте numastat -p, узгодьте CPU і локальність пам’яті (один інстанс на сокет) і уникайте випадкового крос-вузлового трафіку.
7) Симптом: «Прокачав CPU» і не бачимо покращення
Корінь: Вузьке місце в іншому місці: затримка сховища, мережа, блокування в базі даних, пам’ятні стаґнації або серіалізація.
Виправлення: Прогоніть швидкий план діагностики. Доведіть, що CPU — обмежуючий ресурс, перш ніж витрачати гроші або переписувати код.
Перевірні списки / покроковий план
Чекліст A: Перед тим як купувати CPU (або святкувати «вищі GHz»)
- Визначте мету: пропускна здатність, p95 латентність, p99 латентність чи вартість на запит. Оберіть одну головну метрику.
- Захопіть базову лінію: використання CPU по ядрам, ефективна частота під навантаженням, прикладний рівень промахів кеша, iostat-латентність, мережеві ретрансляції.
- Класифікуйте навантаження: обчислювальне, пам’ятне, з блокуваннями, I/O-важке або змішане.
- Знайдіть форму масштабування: чи подвоєння інстансів подвоює пропускну здатність? Якщо так — масштабування вшир може обіграти масштабування вгору.
- Визначте «хвостові ризики»: паузи GC, fsync, блокування БД, шумні сусіди, тротлінг. Вони домінують в p99.
- Обирайте апарат на підставі доказів: більше кеша для пам’яттєвих робіт, стійка потужність для обчислювальних, краще сховище для I/O-важких систем.
Чекліст B: Коли латентність регресує після оновлення апаратури
- Підтвердіть тротлінг:
turbostat+ записи dmesg про теплові події. - Уніфікуйте BIOS і політику живлення: переконайтеся в однакових налаштуваннях по всьому кластеру.
- Перевірте NUMA: локальність і прив’язки для великих процесів.
- Переконайтесь у паритеті ядра й мікрокоду: несумісності дають заплутані різниці.
- Порівняйте perf-лічильники: проксі IPC і рівні промахів кеша; не покладайтеся лише на CPU%.
- Лише потім профілюйте код: ви хочете виправляти софт на стабільній апаратній поведінці.
Чекліст C: Покрокова відладка продуктивності в продакшні (досить безпечно)
- Почніть із симптомів: p95/p99, рівні помилок, ретраї, довжини черг.
- Перевірте насичення: по-ядрове використання CPU, черга виконання, заблоковані задачі.
- Перевірте пам’ять: великі fault’и, свопінг, OOM kills, поведінку аллокатора якщо видно.
- Перевірте сховище: iostat await/глибина черги; Dirty/writeback якщо багато записів.
- Перевірте мережу: ретрансляції/дропи, переповнення listen-черги, softirq CPU.
- Коротко профілюйте:
perf topабоperf statна 10–30 секунд, а не на годину. - Зробіть одну зміну: відкотіть ризиковані «оптимізації», обмежте конкурентність, відкоригуйте політику, а потім знову виміряйте.
FAQ
1) Якщо GHz не має значення, навіщо CPU все ще його рекламують?
Тому що іноді він має значення, і тому що його легко продавати. Частота все ще впливає на продуктивність, але вона вже не домінуючий важіль
для сучасних навантажень. Стійка продуктивність залежить від обмежень потужності, охолодження, IPC, поведінки кеша і локальності пам’яті.
2) На що дивитись замість GHz при виборі серверів?
Підбирайте апарат під навантаження: розмір кеша і пропускна здатність пам’яті для дано-важких сервісів, стійка потужність і векторні можливості для обчислювальних задач,
та латентність/IOPS сховища для записо-важких систем. Також: топологія NUMA, кількість ядер у порівнянні з ліцензуванням і реальна стійка частота під вашим навантаженням.
3) Чому «загальний CPU%» вводить в оману?
Бо це усереднення по ядрах і приховує прилипання. Одне забите ядро може домінувати над латентністю, поки інші простоять.
Завжди дивіться статистику по ядрах і чергу runnable. Також перевіряйте iowait і заблоковані задачі, щоб відрізнити очікування від роботи.
4) Чи допомагає turbo boost для продакшн-наванттажень?
Може допомогти, особливо для сплесків і одно-потокових піків. Але turbo опортуністичний: він залежить від теплового/потужного запасу.
Під стійким навантаженням багато систем опускаються близько до базової або проміжної частоти. Виміряйте Bzy_MHz під реальним навантаженням.
5) Чи завжди більше ядер краще за вищі такти?
Ні. Більше ядер допомагають пропускній здатності, якщо навантаження масштабується і не конкурує. Вищі такти допомагають одно-потоковій або слабо паралельній роботі.
Реальна відповідь: спочатку ідентифікуйте вузьке місце. Якщо ви обмежені затримкою пам’яті, ні те, ні інше не допоможе так, як покращення локальності.
6) Чому деякі оптимізації підвищують кількість промахів кеша?
Поширені причини: збільшення розміру об’єктів, додавання полів, зростання кардинальності, перехід на структури з великою кількістю вказівників або збільшення конкурентності,
через що потоки витісняють робочі набори одне одного. Промахи кеша часто — це «податок структури даних», а не «проблема компілятора».
7) Як сховище може зробити CPU повільним на вигляд?
Коли потоки блокуються на диску (або мережевому сховищі), CPU простає або чекає, і латентність запиту зростає.
Люди бачать повільні відповіді і думають, що справа в обчисленнях. iostat -x і заблоковані задачі в vmstat зазвичай швидко це виявляють.
8) Який найшвидший спосіб довести, що ви CPU-bound?
Шукайте високу чергу runnable (vmstat r), низький idle, прилипання по ядрах і стабільно низький iowait.
Потім зробіть короткий зразок perf top, щоб підтвердити, що цикли в користувацькому коді, а не в очікуванні на блокування чи I/O.
9) Що таке «dark silicon» і чому це має значення?
Це реальність, що не всі транзистори можуть бути активні одночасно на повній швидкості в межах потужностно-теплових обмежень.
Практично: ваш CPU має пікові можливості, які не можна використовувати всі одночасно. Ось чому важить стійка продуктивність і підбір навантаження.
10) Чи можна «виправити» це обмеженнями контейнера або прив’язкою CPU?
Іноді. Прив’язка може покращити локальність кеша і зменшити джиттер планувальника, але може також створити гарячі точки і NUMA-проблеми.
Ліміти можуть запобігти шумним сусідам, але можуть викликати тротлінг, якщо встановлені занадто низько. Сприймайте їх як хірургічні інструменти: виміряйте до/після.
Висновок: практичні кроки (що робити в понеділок вранці)
Припиніть купувати GHz так, ніби це 2003 рік. Купуйте продуктивність так, як купуєте надійність: підбираючи систему під навантаження і перевіряючи поведінку під реальним навантаженням.
Частота ще частина історії, але вона не є сюжетом.
- Прогоніть швидкий план діагностики для вашого сервісу з найгіршою латентністю й класифікуйте вузьке місце: CPU, пам’ятні стаґнації, сховище чи мережа.
- Захопіть базову лінію невеликою підмножиною повторюваних команд: по-ядрове використання, ефективні MHz, зразок промахів кеша, iostat-латентність, ретрансляції.
- Виправте нудні речі першими: тротлінг, NUMA-локальність, втечі ретраїв і насичення I/O-черг. Це дає драматичні виграші і менше сюрпризів.
- Лише потім оптимізуйте код, керуючись профілями. Якщо гарячий шлях — парсинг JSON і хешування, «більше GHz» — це податок; кращі формати й алгоритми — інвестиція.
- Робіть зміни продуктивності так, як SRE робить зміни надійності: канарки, плани відкату й вимірювані критерії прийняття.
Гонка тактової частоти не закінчилась тому, що інженери стали ліниві. Вона закінчилась тому, що фізика виставила рахунок.
Платіть його вимірюванням, локальністю і здоровим системним дизайном — не примарними сподіваннями і таблицею закупівель.