Замеряем время выполнения в Java.

Замер времени выполнения кода — не редкая задача в разработке. Мы постоянно измеряем, сколько работает запрос к БД, сколько сортируется массив, сколько выполняется тяжёлый алгоритм. Казалось бы, что тут сложного? Написал System.currentTimeMillis() до и после — и готово.

Но на практике всё немного сложнее. В этой статье мы:

  • Создадим готовое решение, которое можно сразу скопировать в проект
  • Разберём, почему стандартные подходы плохи
  • Напишем свой класс MeasureTime с нуля
  • Поймём, как правильно измерять время в разных сценариях

Почему System.currentTimeMillis() — это плохо?

Самый очевидный способ замера времени выглядит так:

Проблема: currentTimeMillis() зависит от системных часов. Если во время замера операционная система скорректирует время (например, через NTP-синхронизацию), вы получите:

  • Отрицательное время
  • Резкий скачок в несколько секунд
  • Некорректные результаты

Правильный инструмент: System.nanoTime()

Java предоставляет специальный метод для измерения интервалов — System.nanoTime(). Он:

  • Не зависит от системных часов
  • Имеет наносекундную точность (на практике — зависит от платформы)
  • Монотонно увеличивается (не может идти назад)

Использовать его просто:

Но каждый раз писать этот код — утомительно. Особенно когда нужно:

  • Измерять несколько участков
  • Получать время в разных единицах
  • Красиво выводить результат
  • Использовать в try-with-resources для автоматического замера

Создаём класс MeasureTime

Давайте напишем универсальный класс, который решит все эти задачи.

Шаг 1: Базовая структура

Начнём с простого: храним время старта и умеем его сбрасывать.

Уже удобно:

Шаг 2: Добавляем кеширование результата

Если мы вызовем stop() дважды, получим два разных числа. Это не всегда удобно — иногда нужно зафиксировать результат и больше его не менять до следующего вызова start().

Добавим поле duration, которое запоминает результат после первого вызова stop():

Теперь сколько раз не вызывай stop() — результат будет один.

Шаг 3: Разные единицы измерения

Наносекунды — это круто, но в реальности мы чаще работаем с миллисекундами. Добавим методы-геттеры:

Теперь можно получить время в разных единицах времени, например в мс.:

Шаг 4: Добавляем имя задачи

Чтобы понять, что именно мы измеряем, добавим поле taskName и будем выводить его в отчётах:

Шаг 5: Поддержка try-with-resources

Самый элегантный способ использования — автоматический замер при выходе из блока кода. Реализуем интерфейс AutoCloseable:

Теперь можно писать так:

Финальный код класса

Соберём всё вместе:

Примеры использования

Базовый замер

Перезапуск таймера

Не забудьте, что Thread.sleep требует обработки InterruptedException.

Try-with-resources (автоматический вывод)

Статические фабричные методы

А почему не JMH?

Вообще, в JAVA есть готовый фреймворк для точного измерения времени — JMH (Java Microbenchmark Harness). Он позволяет честно вычислить производительность кода. Есть конечно же «НО».

JMH заметно усложняет код и процесс, делает это осознанно, чтобы дать взамен абсолютно достоверные результаты, которые класс MeasureTime дать не сможет. Это не «утяжеление ради утяжеления», а необходимость для борьбы с хитростями JVM.

Класс MeasureTime хорош для быстрого замера в продакшене, но он дает «сырые» данные. Проблема в том, что JVM — умная система :

  • JIT-компиляция: JVM может оптимизировать ваш код во время выполнения. Первый запуск метода может быть медленным, а сотый — быстрым. Наш таймер этого не учитывает и может показать «среднюю температуру по больнице» .
  • «Мертвый» код: JVM может понять, что результат метода нигде не используется, и просто не выполнить его. Наш таймер покажет очень маленькое время, не отражающее реальную работу.

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

Мало букафф? Читайте есчо !

Как правильно измерить длину строки в Java: от length() до графем

Июль 23, 2026 г.

Строки в Java кажутся простыми, из коробки поддерживается UTF-16, но стоит вам добавить эмодзи, и привычный length() выдаёт «магические» числа. В этой статье разберём, как на самом деле устроены строки в Java, почему эмодзи занимают два char, и как корректно ...

Читать
 

Комментарии к «Замеряем время выполнения в Java.»

Понравилась статья? Есть вопросы? - пишите в комментариях.



Комментарий: