Получить доступ

Какие ошибки чаще всего делают самодельный микробенчмарк бессмысленным?

SeniorJIT и производительность
Ещё спрашивают так:
  • Почему замеру через System.nanoTime в цикле нельзя верить?
  • Коллега замерил два варианта кода через System.nanoTime в цикле и сделал вывод о производительности. Почему такому замеру нельзя верить?
Коротко

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

  • Все три ошибки дают одинаково «впечатляющие» результаты
  • JMH: Blackhole, @State, прогрев и форки
  • Один прогон — не статистика

А ещё Профилировщик (async-profiler) часто полезнее микробенчмарка

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Все три ошибки приводят к одинаково впечатляющему результату: измеряемый код просто исчезает. JIT вправе удалить вычисление, результат которого никому не нужен, и свернуть выражение, вход которого известен заранее. Именно поэтому JMH предлагает Blackhole для потребления результата и аннотацию State для входных данных, которые компилятор не сможет счесть константами, а также сам управляет прогревом и итерациями. К этому добавляются менее очевидные факторы, которые JMH тоже учитывает: разброс между запусками JVM, влияние сборки мусора и профиль, накопленный предыдущими бенчмарками в том же процессе. Общий вывод для собеседования — измерять микропроизводительность вручную практически невозможно, и правильный ответ на вопрос «как вы это измеряли» звучит как JMH.

Что хотят услышать

  • Три классические ошибки и почему.
  • Как решает JMH.

Частые ошибки

  • Верить результатам замера через System.nanoTime без прогрева.
  • Игнорировать разброс между запусками и мерить один раз.

Проверьте себя

Несколько верных вариантов. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Отсутствие прогрева: измеряется интерпретируемый код вместо скомпилированного
  • ✓Мёртвый код: результат нигде не используется, и JIT выбрасывает вычисление целиком
  • ✓Свёртка констант: вход известен на этапе компиляции, и вычисление выполняется один раз
  • ✗Использование long вместо int для накопления результата

Что спросят дальше

  • Зачем нужен Blackhole?
  • Почему один прогон JVM не даёт надёжного результата?
  • Что такое деоптимизация и почему она случается после долгой работы?
  • Когда микробенчмарк вообще не нужен?

Разбор темы

Связанные вопросы

Закрытая бета

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

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем