Performance matters!
1.19K subscribers
11 photos
2 files
63 links
Канал про SRE, Linux и производительность от Александра Лебедева (@alebsys).

Разбираю сбои, ускоряю системы, делюсь опытом.

🔹 Обо мне: alebedev.tech/about
🧑‍💻 Менторинг: alebedev.tech/mentoring
Download Telegram
💥 Выступил на perfconf#10 с неделю назад💥

C докладом:

"Когда код идеален, но система тормозит. Скрытые враги производительности"

(немного пафосно звучит, но что поделать😉)

Рассказывал почтенной публике о влиянии TCP Retransmits и CPU Throttling на производительность приложений — как, зачем и что с этим делать.

Такой ликбез с небольшим deep dive в нюансы.

По ощущениям получилось вполне неплохо, и думаю, стоит повторять такие упражнения в будущем😊

По традиции — спасибо всем причастным! 🙌

P.S. Несколько фото и презентация прилагаются 📸💻

tags: #tcp #cpu
🔥24👍1
Рубрика "Вредные советы" ч.1 — асинхронность в Nginx

В интернетах вращается множество статей из разряда "Top Five Tips for <Твоя технология> in 2024", обещающих повысить, ускорить, оптимизировать.

Подобные гайды передаются из уст в уста и заботливо копируются в инфраструктуры, ведь "на прошлом месте работы это помогло!".
И не важно, что это было в 2012 году, на версии Linux kernel 2.4.x, в другом стеке и вообще не у меня, а у знакомого :)

Такой вот cargo cult.

С другой стороны, чем я хуже? У меня тоже есть парочка советов 😁
—————————————————————————————————

Nginx под капотом использует event‑driven архитектуру. Это когда у воркера есть очередь с ивентами, которую он последовательно "перемалывает".

И чем дольше занимает обработка события (например, чтение с диска), тем дольше ждут остальные в очереди.

Одно из решений — асинхронная обработка событий.

И у Nginx есть что предложить по опциям:
aio threads;
aio_write on;


Теперь вся работа воркера с диском заключается в инициировании запроса, а сам процессинг делегируется отдельным тредам.

Таким образом, воркер способен еще быстрее переключаться между ивентами, ускоряя весь пайплайн!

Пруфы

Измерим latency работы функции ngx_process_events_and_timers (ссылка) — сколько времени уходит на обработку ивента.

1. Без внедрения aio
# funclatency-bpfcc /usr/sbin/nginx:ngx_process_events_and_timers -m -d 100
Function = b'ngx_process_events_and_timers' [147018]
msecs : count distribution
0 -> 1 : 60492 |********************************|
2 -> 3 : 5567 |*** |
4 -> 7 : 3937 |** |
8 -> 15 : 1899 |* |
16 -> 31 : 429 | |
...
avg = 27 msecs, total: 3797767 msecs, count: 136964

2. С aio:
# funclatency-bpfcc /usr/sbin/nginx:ngx_process_events_and_timers -m -d 100
Function = b'ngx_process_events_and_timers' [146165]
msecs : count distribution
0 -> 1 : 103291 |*******************************|
2 -> 3 : 2581 | |
4 -> 7 : 1962 | |
8 -> 15 : 1757 | |
16 -> 31 : 0 | |
32 -> 63 : 374 | |
64 -> 127 : 49 | |
...
avg = 10 msecs, total: 3534364 msecs, count: 342992


Гистограмма показывает значительное сокращение задержек тяжелых операций, а среднее время обработки снизилось почти втрое. Неплохо!
—————————————————————————————————

P.S. Использовать на свой страх и риск, с предварительной проверкой на своей рабочей нагрузке!

Удачи!
👍8🔥1
🔥 Топовые инженеры в сферах SRE, производительности и Linux, на которых стоит подписаться (Linkedin)

👉 Mark Dawson, Jr.
Ведет активную деятельность как на LinkedIn, так и в своем блоге. Море "deep dive" по устройству Linux, его взаимодействию с вычислительными ресурсами и тому, как это влияет на производительность приложений.

👉 Tanel Poder
Создатель 0xtools (утилиты для траблшутинга), частый гость P99CONF и автор множества статей в блоге о Linux и поиске проблем в системах.

👉 Jose Fernandez
Двигает тему eBPF в Netflix, разрабатывая утилиты для повышения наблюдаемости и надежности систем. Активно делится своим опытом с сообществом.

👉 Viacheslav Biriukov
В бытность Яндекса читал лекции в КИТ, а позже завел блог, где простыми словами рассказывает про внутреннее устройство Unix-систем. Супер познавательно!

🎯 Бонус трек — @bobrik (github)
Создатель ebpf_exporter и активный контрибьютер в популярные open-source решения. Его код полезно и интересно читать. А еще ведет страничку в Mastodon про eBPF, Linux и все вокруг.

💬 А кто у вас в подписках?
🔥13
The Art of System Debugging — Decoding CPU Utilization

Или как баг в Java вызвал перегрузку CPU из-за избыточного чтения cgroupfs.

Заметка показывает, как eBPF помогает быстро находить сложные проблемы, и насколько труднее обходиться без него.

Статья интересна:

1. обилием реальных кейсов с использованием bcc утилит — всегда полезно увидеть, как коллеги исследуют системы с их помощью;

2. баги связанные со spinlock сложны для диагностики - создают ложное впечатление работы (высокий CPU System Time), хотя на деле система просто "активно ждет", перегружая процессор. Поэтому такие расследования всегда увлекательны.

В общем два в одном;)

tags: #cpu #troubleshooting
👍7
Рубрика "Вредные советы" ч.2 — больше не всегда лучше.

Увеличение размера очередей - один из самых частых и эффективных советов по тюнингу, который можно услышать.

И сложно спорить, всего один параметр, а сколько пользы:
* сглаживание всплесков нагрузки;
* меньше переполнений => меньше потери данных;
* пропускная способность растет, как и эффективность обработки (пакетами, а не штуками);
* больше асинхронности, меньше боимся "морганий";
* ...

Но у любого совета, пусть и очень хорошего, всегда найдутся недостатки.

Представим два сервиса (1 и 2), взаимодействующих по сети через большую очередь, например на сетевой карте (2).

Пока (2) успевает обрабатывать поток данных, все работает гладко, с описанными выше преимуществами.

Но как только (2) замедляется на значительное время, могут возникнуть проблемы:

* latency каждого пакета в буфере растет кумулятивно, а хвосты ожидают слишком долго;
* срабатывают таймауты (на уровне приложения, TCP) и происходит переотправка, еще больше нагружая очередь;
* все накопленные данные будут обработаны (2), даже если они давно устарели;
* из-за отсутствия своевременной обратной связи TCP (1) реагирует с опозданием — отсутствует failfast;
* перегрузка накапливается в одной части системы, вместо того чтобы равномерно распределяться — отсутствует backpressure.

Список можно продолжить.

Вывод: не следует слепо следовать интернет-советам — всё нужно ставить под сомнение, проверять и подбирать оптимальные параметры именно под вашу систему.

P.S. проблеме раздутых буферов в свое время даже дали название - bufferbloat. Подробнее почитать о ней можно на www.bufferbloat.net.

tags: #network #tcp #theory
👍7
Задержка любой операции, будь то ответ базы данных или обработка HTTP запроса, всегда совокупность задержек на более низких уровнях.

Например, чтение из базы данных состоит из множества этапов:
* формирование запроса
* создание TCP сокета
* обработка и маршрутизация на уровнях ниже
* ожидания в очередях и обработка сетевой картой
* поход по сети, и тд. и т.п.

Потому наблюдение за работой всех уровней — ключ к точному и оперативному анализу состояния системы.

Иначе можно искать задержку на дисках, а причина окажется в исчерпанном пуле соединений к базе. И пока разберемся что к чему, потеряем время, силы и деньги.

#latency
🔥10👍4
CPU Usage не так прост в интерпретации, как может показаться.

Сложность в том, что показатель включает в себя не только работу CPU, но и время обращения к памяти.

А так как память на порядки медленнее процессора, то на ожидание ответа может уходить 90%+ времени.

Чтобы точнее интерпретировать CPU Usage стоит присмотреться к показателю IPC (Instructions Per Cycle) - сколько процессор выполняет инструкций за один такт.

В условиях современных суперскалярных процессоров этот показатель может достигать четырех и более инструкций.
Хотя в реальных нагрузках значение IPC будет существенно меньше (0.7 - 1.5).

Таким образом высокий CPU Usage при низком IPC (<1) может говорить не о недостатке вычислительных мощностей (и это первое, что приходит в голову), а о проблемах с IO - недостаток кешей и/или их плохая локальность, слишком частое обращение к памяти и подобное.

Для лучшего погружения в тему читай:
* CPU Utilization is Wrong от Brendan Gregg;
* IPC is to CPU% What Milk is to Cinnamon Toast Crunch от Mark Dawson.

——————————————
P.S. получить значение IPC можно с помощью node_exporter через perf коллектор, например так:
sum(rate(node_perf_instructions_total{instance=~"$node",job="$job"}[$__rate_interval])) / sum(rate(node_perf_cpucycles_total{instance=~"$node",job="$job"}[$__rate_interval]))

———————————————
P.P.S. этот же пост, но на linkedin.

tags: #cpu #theory #linux
👍12🔥621
Effect of Hyper-Threading in Latency-Critical Multithreaded Cloud Applications and Utilization Analysis of the Major System Resources

Как гиперпоточность/SMT* влияет на производительность различных типов приложений в облачных средах.

Цель исследования — выяснить, какие типы нагрузок выигрывают от SMT, а какие нет.

* SMT позволяет одному физическому процессору выполнять несколько потоков одновременно.

1. Авторы выяснили, что приложения, активно работающие с вводом-выводом (базы данных, очереди, файловые и веб-серверы, кеши), нейтральны к включению SMT.

Их производительность в большей степени зависит от скорости памяти, дисков и сетевых карт, а не от работы процессора.

👉 Потому включение SMT позволяет лучше утилизировать оборудование и экономить ресурсы.

2. Приложения с высокой нагрузкой на процессор (рендеринг видео, сложные расчёты, криптография, high-frequency trading и т. д.) напротив реагировали на SMT негативно - потоки начинают конкурировать за общие ресурсы физического ядра, что приводит к росту задержек.

👉 В окружениях с CPU-bound нагрузкой рекомендуется отключать SMT.

Не стоит слепо доверять любым исследованиям и это не исключение. Хорошо рассматривать их как повод разобраться глубже и провести свои тесты, учитывающие конкретную специфику.

P.S. Кстати метрика IPC (instructions per cycle), которую мы недавно обсуждали, должна помогать в определении профиля нагрузки.
👍10
Мониторинг TCP: метрики Zero Window 🚀

Протокол TCP обеспечивает множество функций, включая управление перегрузками.

Для этого используется механизм скользящего окна (sliding window) — объём данных, который отправитель передаёт без подтверждения от получателя.

Размер окна динамически регулируется в зависимости от объёма свободного места в буфере получателя (net.ipv4.tcp_rmem).

Когда буфер получателя заполняется (получатель не успевает за отправителем), TCP расценивает это как перегрузку и уменьшает размер окна в ACK-сегменте вплоть до нуля (Zero Window Advertisement).

Таким образом, при корректной настройке скорости между отправителем и получателем, переполнения очередей удаётся избежать.

С одной стороны, это позволяет избежать потерь пакетов, ретрансмитов и лишней нагрузки на сеть. С другой — мы можем не заметить, что получатель замедлился, и проблема останется скрытой.

❗️❗️❗️Интерпретация метрик ниже ошибочна, за исправленным описанием прошу сюда https://t.iss.one/troubleperf/65 ❗️❗️❗️

К счастью /proc/net/netstat позволяет отслеживать события, связанные с нулевым окном:
* TCPFromZeroWindowAdv — сколько раз отправитель получил уведомление о нулевом окне;
* TCPToZeroWindowAdv — сколько раз получатель установил нулевое окно;
* TCPWantZeroWindowAdv — общее время, когда отправитель не мог отправить данные из-за нулевого окна;
* TCPZeroWindowDrop — сколько раз отправитель отбрасывал пакеты из-за нулевого окна.

Эти метрики вместе с классическими показателями переполнения буфера и out-of-order очереди позволяют точнее оценивать состояние системы и вовремя выявлять возможные проблемы.

☝️ показатели нулевого окна доступны в node_exporter через коллектор netstat


P.S. Лайк можно занести сюда.

tags: #tcp #linux
🔥163
Рубрика "Вредные советы", №3. Swap.

Есть одно наблюдение и один факт:

* наблюдение: большинство советов по настройке подсистемы памяти Linux рекомендуют либо полностью отключить swap, либо установить vm.swappiness на минимальные значения.
* факт: в большинстве случаев по умолчанию swap включен, а vm.swappiness установлен на 60.

Не кажется ли странным такой диссонанс?

# Немного про память

Для начала краткий экскурс в то, как работает память в Linux.
Память делится на страницы, которые бывают двух типов: анонимные и file-backed.

- Анонимные страницы содержат данные, созданные во время работы приложений (например, heap или stack).
- File-backed страницы — это файлы, загруженные с диска и хранящиеся в файловом кеше.

Когда система испытывает дефицит памяти, она решает, какие страницы можно выгрузить, чтобы освободить ресурсы. В этом выборе участвует параметр vm.swappiness: чем ниже его значение, тем чаще система будет очищать файловый кеш, сохраняя анонимные страницы с более высоким приоритетом.

Кстати, swap используется только для анонимных страниц. File-backed данные, находящиеся на диске, можно всегда подгрузить заново.

В итоге, отключение swap или минимальные значения vm.swappiness позволяют держать в памяти анонимные страницы до последнего, что может приводить к ошибкам OOM.

---------------------
Возвращаясь к началу: какие системы пострадают от приоритета анонимных страниц над файловым кешем? Где, по вашему мнению, стоит повысить vm.swappiness?

Давайте обсудим — это интересно!

P. S. поддержать лайком на Linkedin
5
Анализируя работу подсистемы памяти я часто обращаюсь к метрикам из /proc/vmstat - объем просканированных (pgscan) и украденных (pgsteal) страниц:

pgscan_kswapd
pgsteal_kswapd
pgscan_direct
pgsteal_direct


Показатели помогают понять, как система аллоцирует страницы при нехватки свободной памяти.

Что такое pgscan и pgsteal

* pgscan - сколько страниц было просканировано в поисках кандидатов на высвобождение;
* pgsteal - сколько из просканированных страниц удалось высвободить (украсть).
Scan/steal процессы могут быть запущены либо фоновым kswapd, либо напрямую приложением (direct).

Причем наличие kswapd в вакууме ничего плохого не подразумевает - демон трудится в бекграунде, чтобы держать определенное кол-во свободных страниц в системе.

А вот наличие direct может настораживать: похоже что kswapd не справляется и приложения явным образом требует предоставить ей памяти. Этот процесс уже происходит в foreground и чреват потерей производительности.

Как интерпретировать значения

* абсолютные значения - чем выше значения, тем чаще свободная память падает до минимума и система вынуждена принимать меры;
* соотношения pgsteal/pgscan - высокое значение (95%+) говорит, что большая часть просканированных страниц успешно освобождается (это хорошо). Низкое напротив - система тратит много ресурсов на сканирование, прежде чем найдет подходящие страницы для освобождения.

Как получить значения в grafana

node_exporter в помощь:
node_vmstat_pgscan_direct
node_vmstat_pgsteal_direct
node_vmstat_pgscan_kswapd
node_vmstat_pgsteal_kswapd


Итого

Резюмируя, если значения pgsteal, pgscan растут это сигнал, что память в системе переутилизирована и хорошо бы обратить на это внимание.

Решения проблемы в вакууме нет, все зависит от кейса: где-то будем докидывать памяти, где-то расширять swap, где-то анализировать потребление памяти приложением, а где-то хватит и лимитов на нее.
🔥11👍4
𝗚𝗶𝘁𝗟𝗮𝗯 выделяется среди других компаний своими открытыми репозиториями с множеством полезных гайдов и обсуждений 💬

В одном из таких материалов — заметке "𝗛𝗼𝘄 𝘁𝗼 𝘂𝘀𝗲 𝗳𝗹𝗮𝗺𝗲𝗴𝗿𝗮𝗽𝗵𝘀 𝗳𝗼𝗿 𝗽𝗲𝗿𝗳𝗼𝗿𝗺𝗮𝗻𝗰𝗲 𝗽𝗿𝗼𝗳𝗶𝗹𝗶𝗻𝗴" — автор объясняет, что такое 𝗳𝗹𝗮𝗺𝗲𝗴𝗿𝗮𝗽𝗵, зачем он нужен, как собирать данные и какие трудности могут возникнуть при анализе этих красно-желтых графиков.

Заметка также содержит практические примеры интерпретации 𝗳𝗹𝗮𝗺𝗲𝗴𝗿𝗮𝗽𝗵. Для сбора данных используется linux-perf: он добавляет оверхед, но подходит для старых версий ядер.

На ядрах 4.19+ лучше использовать eBPF-инструмент profile от bcc.
🔥7👍2