B6. Профілювання
Остання робота курсу застосовує попередні модулі до одного практичного
питання: чому це повільно? Головна навичка тут полягає в порядку дій.
Профілювальник функцій показує, де програма рахує, але спершу треба
з’ясувати, чи вона взагалі рахує, чи чекає на диск або на пам’ять.
Шлях read() через ядро і кеш сторінок описано в модулі 13,
рядки кеша і промахи в модулі 2, а трасування через
eBPF у модулі 18.
Після цієї роботи ви зможете:
- за
topі станом процесу сказати, чи бракує програмі процесора, чи вона чекає на ввід-вивід; - прочитати вивід
strace -cі назвати системний виклик, у якому минає час, і скільки разів він викликається; - знайти гарячу функцію через
perf recordіperf report; - за IPC і
cache-missesізperf statвідрізнити обчислення від очікування пам’яті; - показати розподіл затримок диска через
biolatencyабоiostat -xz.
Так виглядає перша година будь-якого розбору «сервіс став повільним»: перш ніж чіпати код, треба довести числами, де втрачається час, а після виправлення виміряти ще раз.
Завдання
Section titled “Завдання”Результат роботи — звіт із трьома розібраними випадками повільної програми: для кожного названо причину, доведено її вимірюванням і показано числа до й після виправлення.
Що зробити: три задачі нижче. У кожній треба знайти причину, довести її вимірюванням і виправити, а потім показати числа до і після. Ідіть за «Порядком дій»: спершу з’ясувати, чекає програма чи рахує, і лише потім брати профілювальник.
-
Програма, що чекає.
Візьміть або напишіть програму, яка читає файл дрібними порціями по 1 байту. Знайдіть це через
strace -c, виправте буферизацією, покажіть різницю в кількості системних викликів і в часі (модуль 3). -
Програма, що промахується повз кеш.
Обхід двовимірного масиву за стовпцями замість рядків. Доведіть через
perf stat, що справа в роботі з пам’яттю, а не в кількості операцій: кількість інструкцій має лишитися майже тією самою (модуль 2).Дивіться передусім на
cache-references, не лише наcache-misses: вибухає кількість звернень за межі L1. Для звірки, масив 3000×3000 (34 МіБ), однакові 127 млн інструкцій в обох випадках:Обхід cache-references cache-misses за рядками 2.0 млн 1.35 млн за стовпцями 35.8 млн 1.59 млн -
Система, що гальмує через диск.
Створіть навантаження (
fioабоddу циклі), знайдіть винуватця черезiostat -xzіbiolatencyз bpftrace, покажіть розподіл затримок (модуль 13, модуль 14).
Чого робити не треба. Не оптимізуйте наосліп: зміна без виміру
до і після не зараховується. Флейм-графи і власні програми bpftrace
лишаються для розділу «Далі, якщо цікаво».
Обмеження. Для задачі 2 потрібна програма на C, зібрана з -g:
інакше perf report покаже адреси замість імен функцій. Для задач 1 і 3
мова довільна.
Що записати у звіт:
- для задачі 1: кількість системних викликів і час зі
strace -cдо і після буферизації; - для задачі 2:
instructions,cache-referencesіcache-missesзіperf statдля обходу за рядками і за стовпцями; - для задачі 3: розподіл затримок із
biolatencyабоr_await/w_awaitзiostat -xzі назву процесу, що створював навантаження; - для кожної задачі: стан процесу і
%waзtopна першому кроці порядку дій і висновок, який ви з них зробили.
Готово, коли:
- ви можете підтвердити командою кожне із семи тверджень таблиці «Що треба вміти підтвердити»;
- у звіті для кожної з трьох задач названо причину і є числа до і після виправлення;
- звіт містить чотири пункти вище.
Перед початком
Section titled “Перед початком”- Прочитайте в модулі 13 розділи «Шлях одного
read()» і «Буферизація і кешування», у модулі 2 розділ «Ієрархія пам’яті», а в модулі 18 розділ «eBPF: ядро стало програмованим». Для задачі 1 згодиться розділ «Скільки це коштує» з модуля 3. - Vagrant-машина з архіву має
linux-perf,bpftrace,fioіsysstat(iostat). На власній системі поставте те саме черезsetup/provision.sh: він до того ж знижуєperf_event_paranoidіkptr_restrict, без чогоperfіbpftraceне бачать символів ядра. - Скрипт
biolatencyвходить до прикладівbpftrace. Заготовок іcheck.shдля цієї роботи в архіві немає: результат підтверджується таблицею тверджень і звітом.
Порядок дій
Section titled “Порядок дій”Це головний матеріал роботи. Запам’ятайте послідовність: вона економить години.
-
Чи це взагалі процесор?
top: якщо процес у станіSабоD, а%waвисокий, то процесора вистачає і програма чекає. Профілювальник функцій тут не допоможе. -
На чому саме чекає?
strace -T -cпокаже, у яких системних викликах минув час. Для стануD—cat /proc/<pid>/wchanабоstack: там назва функції ядра, у якій процес заснув. -
Якщо процесор — то де?
perf topдля живої картини,perf record+perf reportдля розбору. Дивитися спершу на частку, назви функцій потім. -
Чи це взагалі обчислення?
perf stat: відношення інструкцій до тактів (IPC). Значення менше одиниці означає, що процесор чекає на пам’ять замість рахувати (модуль 2). Далі дивітьсяcache-missesіdTLB-load-misses(модуль 11). -
Якщо потрібне те, чого немає в готових інструментах —
bpftrace.
Що треба вміти підтвердити
Section titled “Що треба вміти підтвердити”| Твердження | Чим доводиться |
|---|---|
| Ви відрізняєте очікування від обчислень | top %wa + стан процесу |
| Ви знайшли, у якому виклику час | strace -c -T |
| Ви знайшли гарячу функцію | perf report |
| Ви знаєте, чи процесор рахує чи чекає | perf stat, IPC |
| Промахи кеша виміряні, а не припущені | perf stat -e cache-misses |
| Затримки диска показані розподілом | biolatency або iostat -xz |
| Виправлення дало ефект | числа до і після для кожної задачі |
Часті помилки
Section titled “Часті помилки”Профілювання без символів. perf report показуватиме адреси замість
імен. Потрібні -g при збірці й пакети з відлагоджувальними символами.
Заміри без прогріву. Перший прогін читає з диска, а наступні вже з кеша сторінок (модуль 13). Різниця в сто разів, і до вашої оптимізації вона не має жодного стосунку.
Оптимізація не того. Функція займає вісімдесят відсотків часу, але викликається там, де програма й так чекає на диск. Тому й починають із першого пункту порядку дій.
strace як профілювальник. Він сповільнює програму в рази, бо
перехоплює кожен виклик. Для розподілу часу між викликами придатний,
для абсолютних чисел ні.
Висновок без другого виміру. «Стало швидше» без чисел до і після результатом не вважається.
Далі, якщо цікаво
Section titled “Далі, якщо цікаво”Побудувати флейм-граф із perf record і подивитися, як виглядає
той самий профіль у вигляді дерева викликів. Або написати власний
однорядковий bpftrace, що рахує розподіл затримок конкретного
системного виклику.