about:performance
1.43K subscribers
14 photos
2 files
85 links
Канал про SRE, Linux и производительность от Александра Лебедева (@alebsys).

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

🔹 Обо мне: alebsys.github.io/about
🧑‍💻 Консультации: alebsys.github.io/mentoring/
💰 Поддержать: https://boosty.to/troubleperf
Download Telegram
Читать научные публикации это не только полезно, но бывает и чертовски сложно. Нередко закапываешься в деталях и останавливаешься по середине.

Для меня это актуальная проблема и я постоянно ищу как оптимизировать процесс обучения.

Один из фреймворков работы с white paper описан в статье A Software Engineer's Guide to Reading Research Papers.

Вкратце алгоритм, в зависимости от целей, разбивается на 4 этапа:

1. Big picture: пробегаемся по abstract + intro + conclusion.
На этом шаге будет понятно насколько исследование релевантно нашему запросу (если нет, то проходим мимо) и требуется ли погружаться подробнее. Подозреваю, что где-то тут и пролегают те самые "80 / 20"

2. Deep dive: если решили капать дальше, то читаем пропущенные раннее разделы, выписываем все что непонятно + интересные ссылки. Цели понять всё досконально на этом этапе нет, все впереди)

3. Background: гуглим что было непонятно, обсуждаем с AI, пробегаемся по ссылкам (часто хватит abstract)

4. Connect dots: возвращаемся к сложным разделам уже новым с контекстом и пониманием в голове.

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

Вспоминается чтение книги с кабанчиком, когда в какой-то момент понимаешь, что и без того не тоненькая книга лишь верхушка айсберга, а под водой десятки / сотни ссылок на исследования, которые надо осилить 🙂.

Делитесь своими подходами к обучению. Хорошего дня!
2👍15🔥61
О бенчмаркинге, часть 1

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

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

Брендан Грегг в своё время ввёл наглядную терминологию: 
* Passive Benchmarking
* Active Benchmarking

———

Passive Benchmarking простой и распространённый подход: настраиваешь окружение, запускаешь нагрузку, получаешь на выходе цифры и в дальнейшем ими руководствуешься.

Но это как раз тот случай, когда «просто» не значит «лучше».

Проблемы таких замеров:
* риск измерить не то, что планировалось изначально
* непонятно, что именно ограничивает производительность
* нельзя отличить систематическое отклонение от шума (об этом позже)
* остаемся без ответа, почему получены именно такие результаты
* сами бенчмарки могут содержать баги, что останется от нас скрыто

«Бенчмаркаешь A, на самом деле измеряешь B, а выводы делаешь о C». ©


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

———

В противовес ему стоит Active Benchmarking (AB).

Помимо настройки окружения требуется активное наблюдение за системой во время прогона.

Задача понять:
* то ли мы меряем, что планировали
* что ограничивает производительность
* согласуется ли наблюдаемое поведение с нашей моделью системы
* что нужно изменить, чтобы улучшить результат

AB способен дать более надёжный результат.

Цена этого: более высокие требования к проведению эксперимента. Нужно не только уметь настроить окружение, но и верно интерпретировать наблюдаемое.

Алгоритм:
1. Собрать данные о работе системы, тулинг в помощь (perf, bcc, iostat, bpftrace, tcpdump, ...)
2. Интерпретировать, как реагирует система (методологии USE, RED, off-CPU, TSA, ...)
3. Применять в цикле:
запустил
└─ пронаблюдал
└─ сформулировал гипотезу во что упираемся
└─ проверил в следующем прогоне
└─ повторил


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

———

Вывод

Сырые цифры от Passive Benchmarking могут выглядеть правдоподобно и при этом вести к неверным и дорогим решениям.

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

Не похоже на надёжную стратегию

Active Benchmarking напротив, позволяет избежать ловушки «бенчмаркаешь A, измеряешь B, делаешь выводы о C».

Цифры, полученные таким методом, поддаются объяснению, их можно оспорить и воспроизвести.

И на них уже можно опираться при принятии инженерных решений.

———

Что почитать
- Active Benchmarking
- CPU Benchmarks and Bad Tinder Dates
- Performance Methodologies
- Producing Wrong Data Without Doing Anything Obviously Wrong (тут может помочь заметка о чтении white paper)

To be continued...

———

Поддержать лайком на Linkedin.
🔥12👍63
Вышла вторая часть серии про бенчмаркинг (первую ищи тут).

Ее центральная мысль: performance is a shape, not a number.

Каждый отдельный замер это всего лишь один сэмпл из полного распределения.

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

В этой части:
* почему производительность это распределение, а не число
* что такое шум, откуда он берётся и каких бывает типов
* как бороться с каждым из них
* и почему борьба с ним не имеет конца

Полная версия появится здесь через 7 дней вот уже совсем скоро...
🔥101
Походил, подумал, не нужен в канале этот ранний доступ.

Добавил себе геморроя на ровном месте. Лучше откатить раньше, чем позже.

Поэтому реверт — возвращаюсь к исходному формату публикаций.
2👍1811🤝2💯1
О бенчмаркинге, часть 2

(первая часть тут)

Производительности в вакууме не бывает

Состояние одной и той же системы от запуска к запуску бенчмарков всегда разное. Даже если зафиксированы все статические параметры (настройки OS и рантайма, CPU affinity, etc), то температура процессоров, состояние кешей, layout кода в памяти всё равно плавают. Что уж говорить про внешне схожие окружения - там различий может быть еще больше.  

Следовательно результаты на выходе всегда различаются.

Так какой из них нам взять за основу?

———

Помогает формулировка от Ben Sigelman: «Performance is a shape, not a number».

Производительность это всегда распределение, а не одно конкретное число. Не существует одного единственного, правильного значения. 

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

Если углубить, то и внутри одного запуска мы всегда получаем распределение:

$ funclatency-bpfcc __sys_sendto -d 10 -u

usecs : count distribution
0 -> 1 : 12433 |************ |
2 -> 3 : 20394 |******************* |
4 -> 7 : 20540 |********************|
8 -> 15 : 1962 |** |
16 -> 31 : 237 | |
32 -> 63 : 19 | |
64 -> 127 : 8500 |******** |
128 -> 255 : 12 | |
256 -> 511 : 0 | |
512 -> 1023 : 4 | |
1024 -> 2047 : 5 | |
2048 -> 4095 : 1 | |
4096 -> 8191 : 2 | |


———

Задача перформанс-инженера сводится к двум вещам:
1. сужать это распределение
2. объяснять, почему оно именно такое

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

Важный момент: шум может быть случайным, а может быть систематическим. Бороться с ними нужно по-разному.

———

Случайный шум (random noise) это то, что возникает непредсказуемо, без видимой системы. Например, фоновый процесс случайно попал на наше ядро в одних прогонах и не попал в других. Или соседнее ядро внезапно дало всплеск нагрузки на общий L3.

Лечится количеством прогонов: чем их больше, тем сильнее усредняем случайные отклонения, и тем точнее итоговая оценка.

Систематический шум (systematic bias), уже другое явление. Какой-то фактор стабильно сдвигает измерения в одну и туже сторону. Например IRQ, прибитый к нашему ядру, просыпается через равные промежутки. Такой тип шумов (или отклонений) не лечится количеством прогонов, из раза в раз будем получать искаженный результат. 

В "Producing Wrong Data Without Doing Anything Obviously Wrong",  авторы показали, что даже размер переменных окружения может вносить существенные искажения в итоговый результат. 

С систематическим шумом борются наблюдением и рандомизацией факторов, см. Stabilizer.

———

Это объясняет, почему Passive Benchmarking плох, даже при тысяче прогонов: он не отличает один тип шума от другого. Active Benchmarking, помимо прочего, как раз про то, чтобы такие смещения находить.

Ранее мы говорили о цикле в Active Benchmarking: запустил → пронаблюдал → сформулировал гипотезу → проверил → повторил.

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

Далее поднимают голову соседи по L3 кешу... 

По своей природе это похоже на дрейфующее бутылочное горлышко в производительности: всегда что-то будет в топ-1.

Следующим возникает естественный вопрос: "где и когда остановиться?" To be continued.

———

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

———

Поставить лайк на Linkedin
🔥863
Channel name was changed to «about:performance»
Чего только не придумаешь в отпусках!

Например, новое название канала: about:performance

Теперь так.
1👍263🦄1
Упрощенно нарежем типичную функцию на две части:

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

Мы хотим, чтобы первая часть была максимально дешёвой относительно второй (кэп).

А вот что менее очевидно: объём полезной работы далеко не всегда линейно влияет на длительность функции.

———

Наглядный пример: системный вызов sendto, для отправки UDP-датаграмм.

Зависимость длительности вызова от размера payload на скрине.

Интересно, что при минимальном объеме данных в 1 байт (плюс заголовки), время работы внутри sendto ~1.8мкс.

Но если увеличить payload до 512 байт, длительность вырастает всего в 1.25x. И дальше с ростом, почти не меняется. 

(цифры на других системах могут отличаться, перепроверяйте)

Бо́льшая часть времени внутри sendto уходит не на сами данные, а на сопутствующую работу: оформить UDP/IP-заголовки, прогнать через сетевой стек, поставить в очередь на отправку.

Всё это происходит вне зависимости того, один байт ты отправляешь или тысячу.

———

И дело не в sendto. Так ведут себя многие вызовы, на которых всё держится: фикса доминирует, а объём данных почти не влияет.

Такое поведение трудно угадать без знания внутренней механики — но из этих деталей и складывается грамотный дизайн системы.

Поэтому не угадывай, замеряй.
🔥104❤‍🔥1
LLM про корректность, не про производительность

пока что

Недавние исследования (раз, два) подсвечивают "особенность" современных LLM:

«... модели хорошо чинят баги и закрывают задачи, но это умение не переносится на оптимизацию производительности. Современные LLM заточены под корректный код, а не под быстрый.»


Причина не в том, что модели "не могут" в перформанс, а в том, как их обучают и оценивают.

Основные бенчмарки (HumanEval, MBPP, SWE-bench) делают упор на корректность генерируемого кода (pass@k). Метрики эффективности (eff@k) существуют, но пока не стали стандартом.

То есть "перформанс" сейчас не входит в KPI моделей.

———

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

За 1.0× брали результат человека-эксперта по кодовой базе:

Top-Expert          1.000×
GPT-5 0.150×
Claude 4.1 Opus 0.098×
Qwen3 Coder Plus 0.064×
Claude 3.7 Sonnet 0.047×
Claude 4.5 Sonnet 0.041×
GLM-4.6 0.026×
GPT-5 Mini 0.019×
Kimi K2-0905 0.008×
Gemini 2.5 Flash 0.008×
DeepSeek V3.1 0.007×
Gemini 2.5 Pro 0.007×


Таким образом, лучшая модель (GPT-5) достигла лишь 15% от ускорения, которое показал человек-эксперт.

А в среднем модели показывали результаты на уровне погрешности.

———

Во второй работе проверяли, можно ли снизить регрессию производительности промптингом. Сравнивали два подхода:

1) few-shot: даём примеры эффективного кода
2) chain-of-thought: просим рассуждать пошагово

За 100% взят уровень регрессий без промпта. Если меньше, то промпт помог, если больше, то навредил. (скрин в комментах)

few-shot почти всегда уводит регрессии ниже 100%, а результаты chain-of-thought неоднозначны: где-то помогает, а где-то делает только хуже.

Как нетрудно догадаться, когда LLM дают примеры эффективного кода (мы же так и делаем, верно?🙂), результат стабильно лучше, чем когда мы просто просим её "хорошо подумать".

———

Среди основных слабостей LLM отмечают:

1) неверно идентифицируют узкое место
2) бросают на полпути, найдя любое ускорение
3) используют костыли вместо системных решений
4) подгоняют решение под тесты, периодически ломая корректность

———

В любом случае, на сегодня "человек с perf'ом" в руках остается важнейшим звеном в вопросах производительности.

А с растущим объёмом генерируемого кода эта роль только усиливается.

———

Хотя вопросы появляются:

1) 15% от "экспертного" уровня это много или мало? И сколько покажет обычный, пусть и опытный, разработчик?
2) Как скоро эффективность кода станет для LLM полноценным KPI?
1👍13🔥21
В продолжение темы про AI.

Хочу порекомендовать канал моего знакомого – Azalio_tech

Миша – топ по Kubernetes и активно интересуется применением AI, как в работе, так и в повседневной жизни.

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

Так что, если тема близка, подписывайтесь!

Хороший контент стоит того, чтобы его поддерживать.
🔥53👎1
Про среднее

У avg сложилась не лучшая репутация:
* чувствителен к выбросам
* скрывает хвосты
* врёт на мультимодальных распределениях и т.д.

И всё это правда. 

Но с одной оговоркой: если производительность не одно число, а распределение, то любой показатель неизбежно упрощает его, а значит может как откровенно врать, так и более-менее честно описывать действительность. 

То есть все зависит от задачи, которую требуется решить, от контекста. 

———

Всем нам нравятся перцентили. Но попробуйте прикинуть с их помощью throughput системы или ёмкость очереди. Вряд ли выйдет (кстати, почему?).

А вот среднее тут будет к месту. 

И наоборот: среднее ничего не скажет про то, как себя чувствует худший по latency 1% запросов.

Чтобы не ошибаться в оценках, сначала стоит сформулировать вопрос, а только потом подбирать под него инструмент. 

Если речь про средние и перцентили, упрощённо можем разложить так:
* сколько всего / хватит ли ёмкости? Это про сумму, то есть про среднее
* насколько плохо бывает? Тут про хвосты, то есть про перцентили

———

В итоге, чем лучше понимаем ограничения каждого инструмента, тем меньше обманываем и себя, и окружающих.
👍155
Please open Telegram to view this post
VIEW IN TELEGRAM
about:performance
Загадка про распределение. #1 Сервис отвечает на запросы. Сняли статистику по длительности ответа: count : 47350 mean : 1021 us p50 : 160 us p90 : 3046 us p99 : 3682 us max : 37807 us Среднее 1021 мкс, а половина запросов укладывается…
Ну окей, первая задачка была не сложной.

1) p50 = 160us: основная масса запросов будет где-то в районе этого числа, считай это мода
2) mean » p50: можно заподозрить, что рядом есть ещё крупная мода, но без гарантий, среднее может просто улететь из-за одного огромного выброса
3) p90 ≈ p99 и оба » p50: право-скошенности скорее нет (иначе p99 был бы кратно выше p90), а раз они рядом, то это скорее отдельная медленная мода
4) max » p99: на третью моду тянет слабо, скорее редкие выбросы, но тоже без гарантий.

И из представленных вариантов лучше всего подходит B, с мультимодальностью.
83
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔21👎1
about:performance
Давайте ещё разок, на этот раз чуть сложнее: count : 44500 mean : 871 us p50 : 1081 us p90 : 1289 us p99 : 5012 us max : 11275 us Задача всё та же: по статистике определить форму распределения. Возможные варианты: A) право-скошенная…
А вот и ответ.

Главный момент: mean < p50 (что ловко подметил @ddpechkin)

И это при настолько высоких p99/max.

В типичном случае mean, за счёт хвостов, тянется вверх. А тут «что-то» его примагничивает вниз.

Мода!

Плюс близкие по значениям p50/p90 намекают, на наличие второй моды.

Все это в совокупе подталкивает к варианту C.
👍7
Продублирую свой комментарий на вопрос:

Стоит задача оценки достаточности мощности оборудования по CPU. Вот уже голову сломали с методикой. Когда смотреть на среднюю, когда на p99 и p90. Пробовали коэффициент вариации(не более 5%) и что-то никуда не пришли пока…🙁


Я касался этой темы в посте о среднем (https://xn--r1a.website/troubleperf/110). Основная мысль в том, что начинать нужно с постановки проблемы, и держа ее в голове, искать решение (подходящую метрику).

«Достаточность CPU» редко бывает самоцелью, скорее нас больше интересует справляется ли система со своей прямой обязанностью: 

* бекап данных заданного объема должен успеть за X (throughput)
* обработка транзакции должна уложиться в Y (latency)

Отсюда и метрики, за которыми хотим следить: 
* для первой задачи подойдет среднее над bytes/s (не над CPU!)
* для второй p95/p99 над длительностью обработки.

И уже через их призму, мы можем смотреть на утилизацию CPU, если нужно понять отчего не пролазим в свои SLO. 

Это если вдруг считаем, что виноват именно CPU (читаем про активный бенчмаркинг тут https://xn--r1a.website/troubleperf/99).

———

Если интересно, не избыточно ли у нас мощностей, то и тут меряем запас по главной метрике (p99/ bytes/s): насколько она далеко от порога SLO.

И в зависимости от нужного запаса либо срезаем, либо добавляем ресурсы.
👍311
Про бенчмаркинг, часть 3
(части 1,2)

Ранее обсудили, что борьба с шумом (noise) процесс бесконечный.
И если поторопиться с выводами, то в шум легко записать сам bottleneck.

Важно их различать. 

Шум это внешний фактор (случайный или систематический), который растягивает распределение задержек системы (см. часть 2). Лечим стабилизацией и изоляцией окружения.

Bottleneck фактор скорее внутренний: то, что напрямую ограничивает производительность системы. Лечим сменой архитектуры, алгоритмов, добавлением ресурсов и подобным. 

———

Практический (анти)паттерн.

Частый способ борьбы с широким распределением (да и вообще подход на все случаи жизни): перебирать доступные параметры в надежде, что какой-то сработает. Б. Грегг поэтично назвал его "Drunk Man Anti-Method".

В генерации таких списков особенно хорош AI, у него богатая фантазия. Туда же и множество статей в интернетах из разряда "топ-10 секретов low-latency в 2026 году".

По форме это похоже на Active Benchmarking (см. часть 1): попробовал, проверил, повторил. Но пропущены ключевые шаги: наблюдение и формирование гипотезы ДО изменения. Без них цикл похож на слепой перебор.

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

Не стоит так делать. 

Фреймворк, на мой взгляд, должен быть примерно таким:
* Наблюдаем за системой доступными инструментами
* Отмечаем аномалии, формируем гипотезу о том, что шумит
* Точечно вносим изменение, проверяющее гипотезу
* Повторяем

Если гипотеза верна, разброс упадёт. Если нет, идем дальше. 

———

Отмечу, что bottleneck может прикидываться шумом, но таким не являться. Например:
* Lock contention
* Работа GC
* Background flushing в БД
* TCP congestion control

Все они срабатывают в случайные моменты, поэтому выглядят как шум. Хотя фактически вызваны внутренними факторами системы, а не чем-то внешним. 

Соответственно лечатся не изоляцией, а изменением кода, настроек runtime или архитектуры системы.

———

В следующей части: где и когда остановиться в борьбе с шумом и bottleneck'ами.
👍8🔥31
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👏41🦄1