С нуля: что такое работа с производительностью на самом деле
Оптимизация производительности — дисциплина с одним правилом — сначала измерь, потом исправь доказанное узкое место. Это карта «с нуля» и восемь слов, которые каждый senior-юнит считает уже знакомыми.
Приложение тормозит. Пользователь нажал кнопку — и две секунды ничего. У тебя есть теория: наверное, база данных, или слишком много JavaScript, или тот цикл, который ты написал на прошлой неделе. Ты тратишь день на переписывание цикла — кнопка всё равно медленная. Оказывается, база всё это время делала full scan по таблице. Ты оптимизировал не то. Этот урок — карта, которая предотвращает эту ошибку: прежде чем менять хоть строку кода ради скорости, нужно найти, куда именно уходит время.
Единственная ошибка, которую предотвращает работа с производительностью
Когда что-то медленно, первый инстинкт — угадать: «наверное, база», «наверное, много JavaScript», «наверное, тот цикл». Догадки кажутся разумными — они основаны на опыте. Они также ошибочны примерно в половине случаев, и действие на основе ошибочной догадки ускоряет то, что и так не было проблемой. Тем временем настоящее узкое место — единственное место, где время реально накапливается, — остаётся нетронутым и тормозит каждого пользователя. Работа с производительностью — это дисциплина не гадать: ты измеряешь, куда уходит время, находишь одно место, которое важнее всего, исправляешь только его и снова измеряешь, чтобы убедиться, что реально помогло.
Сделаешь правильно — небольшое точечное изменение может вдвое сократить время ответа. Сделаешь неправильно — потратишь недели на микрооптимизацию кода, который профайлер показал бы незначимым за тридцать секунд.
Восемь слов, которые остальной трек считает знакомыми
Senior-юниты дальше используют эти термины, не останавливаясь на определениях. Прежде чем разбирать флейм-граф или читать алерт о деградации в проде, эти восемь слов должны уже быть у тебя в голове — как рабочий язык, а не зазубренный список. Вот они, по одному предложению.
| Слово | Что это | Зачем оно |
|---|---|---|
| Latency (задержка) | Сколько времени занимает одна операция — пауза от «отправлено» до «получен ответ». | Потому что пользователь чувствует задержку напрямую; медленный ответ — это проблема latency. |
| Throughput (пропускная способность) | Сколько операций система выполняет в единицу времени. | Потому что система может быть быстрой на каждый запрос, но рухнуть под высокой нагрузкой. |
| Profiling (профилирование) | Запуск инструмента, который записывает, где именно программа тратит своё время. | Чтобы заменить догадки доказательствами до того, как тронуть хоть строку кода. |
| Bottleneck (узкое место) | Единственный самый медленный шаг, ограничивающий скорость всей системы. | Потому что ускорение чего угодно другого не сделает систему в целом быстрее. |
| Percentile (перцентиль, p50 / p99) | p50 = медианный запрос; p99 = самый медленный 1 из 100. | Потому что среднее скрывает хвост — медленный 1% пользователей — это реальные люди. |
| The tail (хвост) | Самые медленные запросы на высоких перцентилях (p99, p999). | Потому что в микросервисах один медленный хвостовой вызов может затормозить весь запрос пользователя. |
| Big-O vs реальная стоимость | Big-O описывает, как стоимость растёт с размером входа; реальная стоимость включает константы, промахи кэша и I/O. | Потому что алгоритм O(n²) на маленьком датасете может обогнать O(n log n) с плохим поведением кэша. |
| Measure-don’t-guess (сначала измерь) | Принцип: каждое решение об оптимизации должно начинаться с данных профайлера, а не с интуиции. | Потому что преждевременная оптимизация — исправление до измерения — тратит время и добавляет сложность. |
Как они складываются вместе
Слова рассказывают одну историю по порядку: ты профилируешь работающую систему, чтобы найти, куда реально уходит время, затем определяешь единственное узкое место, ограничивающее общую скорость. Исправляешь только его, затем профилируешь снова. Оцениваешь результат не по среднему, а по перцентилям — особенно p99, потому что хвост — это то, что реальные пользователи на медленных соединениях или в неудачный момент действительно испытывают. Держишь в голове latency и throughput как два разных измерения: изменение может снизить latency, не увеличив throughput, и наоборот. Помнишь, что big-O — модель роста, а не обещание: в реальности доминируют расположение данных в памяти и I/O, которые асимптотическая нотация игнорирует. И никогда не пропускаешь первый шаг: measure-don’t-guess — не слоган, а единственная привычка, отделяющая продуктивную работу с производительностью от потраченных усилий.
▸Почему это работает
Почему преждевременная оптимизация так плохо репутирована? Потому что она оптимизирует до появления доказательств. Ты тратишь неделю на ускорение не того кода, и теперь этот код ещё и сложнее читать и менять. Настоящее узкое место, нетронутое, по-прежнему определяет время ответа. Профилирование сначала занимает тридцать секунд и показывает ровно те тридцать строк кода, которые заслуживают недели внимания. В этом и весь смысл «сначала измерь».
Это не нужно зубрить
Две честные ремарки перед восхождением. Первая: никто не держит всё это в голове сразу в первый день — ты встретишь каждое слово снова, в своём юните, в контексте, и тогда оно уляжется. Эта страница — вешалка для деталей, а не экзамен. Вторая: среднее врёт удобными способами. Когда дашборд говорит «среднее время ответа: 120 мс», это звучит нормально — но если p99 равен 4 секундам, каждый сотый пользователь ждёт четыре секунды, и при высоком трафике это тысячи реальных людей в час. Senior-инстинкт — смотреть на хвост в первую очередь.
Почему измерение перед оптимизацией важнее инженерной интуиции?
Расставь правильный цикл работы с производительностью:
- 1 Профилировать работающую систему, чтобы найти, куда реально уходит время
- 2 Определить единственное узкое место, ограничивающее общую скорость
- 3 Исправить только это узкое место
- 4 Профилировать снова и проверить перцентили, чтобы убедиться в улучшении
- 01В одном дыхании: каково главное правило работы с производительностью и почему догадки не работают?
- 02Почему senior-инженеры судят о производительности по p99, а не по среднему latency?
Работа с производительностью — одно правило с кучей навешанного словаря: сначала измерь, найди настоящее узкое место, исправь только его, потом измерь снова. Измерительная половина опирается на профайлер — инструмент, который записывает, где программа реально тратит время, заменяя интуицию доказательствами. Оценочная половина опирается на перцентили, а не на среднее: p50 — это медианный опыт, но p99 — это то, сколько ждёт самый медленный каждый сотый пользователь, и хвост важнее среднего в любой системе под реальной нагрузкой. Latency и throughput — два разных измерения: изменение может помочь одному, не помогая другому. Big-O описывает темп роста, а не реальную стоимость; на практике доминируют расположение данных в памяти и I/O. Единственная привычка, которая всё это скрепляет, — measure-don’t-guess: преждевременная оптимизация тратит усилия и добавляет сложность до того, как ты знаешь, что исправлять. Каждое из этих слов ты встретишь подробно в своём юните. Теперь, когда встретишь медленную систему в проде, первый шаг — не правка кода, а запуск профайлера, чтобы узнать, куда реально уходит время.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.