0Pricing
Java Academy · Урок

Выявление узких мест

Сначала измеряйте, затем оптимизируйте

«Выявление узких мест» — бесплатный урок Java Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Измеряйте, не гадайте

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

Интуитивные представления о том, где Java-программа проводит время, обычно ошибочны. JIT-компилятор, сборщик мусора и кэширование делают предположения ненадёжными. Выполните профилирование, найдите настоящее узкое место и исправьте его.

Что такое узкое место

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

Оптимизация чего-либо другого не даст заметной пользы. Закон Амдала формулирует это точно: если 90% времени приходится на один метод, ускорение остальных 10% никогда не даст улучшения более чем на 11%.

Задержка и пропускная способность

Определите, что именно Вы оптимизируете:

  • Задержка — сколько времени занимает один запрос.
  • Пропускная способность — сколько запросов обрабатывается в секунду.

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

Измерение реального времени

Самое простое измерение — замерить реальное время вокруг блока кода с помощью System.nanoTime().

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

public class Main {
    public static void main(String[] args) {
        long start = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < 10_000_000; i++) sum += i;
        long elapsed = System.nanoTime() - start;
        System.out.println("Sum: " + sum);
        System.out.println("Elapsed ms: " + (elapsed / 1_000_000.0));
    }
}

Остерегайтесь прогрева JIT

Java начинает с интерпретации байткода, а затем JIT компилирует часто выполняемые методы в машинный код.

Поэтому первые запуски метода намного медленнее последующих. Наивный цикл измерения в основном измеряет прогрев. Настоящие тесты производительности сначала выполняют прогрев, а затем измеряют установившийся режим — именно это за Вас делает JMH.

Ограничение CPU и ограничение IO

Определите тип узкого места:

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

Профилировщики различают это как время «на CPU» и «заблокированное или ожидающее». Исправления полностью различаются: более быстрые алгоритмы либо больший параллелизм и меньшее число обращений.

Выборка и инструментирование

Есть две стратегии профилирования:

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

В рабочей среде предпочитайте выборку с низкими накладными расходами, например с помощью Java Flight Recorder.

Память как узкое место

Часто настоящая стоимость связана с выделением памяти, а не с вычислениями. Избыточное создание объектов приводит к частому запуску сборки мусора, отнимает ресурсы CPU и добавляет паузы.

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

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Allocation-heavy: a new String each iteration
        List<String> garbage = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            garbage.add("item-" + i);
        }
        System.out.println("Allocated " + garbage.size() + " strings");
        System.out.println("In a hot loop, this churn drives GC pressure");
    }
}

Найдите вершину стека

Профилировщик с выборкой создаёт список методов, упорядоченных по частоте появления в стеке CPU, — это собственное время.

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

Создайте исходную точку

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

После каждого изменения измеряйте снова и сравнивайте результаты. Без исходной точки невозможно доказать, что оптимизация помогла, а многие «оптимизации» только ухудшают ситуацию. Меняйте по одному параметру за раз.

Профилирование при реалистичной нагрузке

Узкое место, обнаруженное на бездействующем ноутбуке, может оказаться не тем, которое будет вредить в рабочей среде.

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

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

Быстрая проверка

Почему одиночные наивные измерения времени выполнения метода Java с помощью System.nanoTime() часто вводят в заблуждение?

Итоги

Поиск узких мест дисциплинированным способом:

  • Измеряйте перед оптимизацией; интуиция обманывает.
  • Выберите цель: задержка или пропускная способность.
  • Определите, ограничена ли работа CPU или IO; следите за сборкой мусора и выделением памяти.
  • Отдавайте предпочтение профилировщикам с низкими накладными расходами, использующим выборку.
  • Учитывайте прогрев компилятора во время выполнения; установите базовый показатель и изменяйте только один параметр за раз.

Часто задаваемые вопросы

Урок «Выявление узких мест» бесплатный?

Да — полный текст урока «Выявление узких мест» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Выявление узких мест»?

Сначала измеряйте, затем оптимизируйте Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Выявление узких мест»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Выявление узких мест
  2. Java Flight Recorder
  3. Анализ с помощью JDK Mission Control
  4. Распространённые флаги настройки JVM
← Назад к Java Academy