⏱ Измеряем время выполнения кода в Java с помощью StopWatch

Вступление

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

В многопоточных системах также полезно измерять время выполнения отдельных потоков (Thread) или асинхронных задач.

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

В этом уроке мы рассмотрим, как измерить время выполнения кода на Java с помощью StopWatch.

Что такое StopWatch?

StopWatch – это служебный класс, находящийся в пакете util. У него очень простой API, он даёт нам возможность определять время выполнения отдельных задач, групп задач и общее время выполнения программы.

Этот класс обычно используется для проверки производительности кода на этапе разработки.

Примечание: StopWatch непотокобезопасен.

Он отслеживает время в наносекундах, полагаясь на System.nanoTime().

Измеряем время выполнения кода с помощью StopWatch

Секундомер относится к базовому пакету утилит Spring:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
</dependency>

Также он есть в spring-boot-starter-web:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

API StopWatch сводится к созданию экземпляра и вызову start() и stop(): так он синхронизирует код с реальным секундомером. При синхронизации вы также можете указать строку, которая будет использоваться в качестве имени или аннотации для связанной задачи. Это помогает дифференцировать их результаты.

Задача – это период между вызовом start() и stop(). Для каждой задачи, созданной при запуске StopWatch, её имя и время выполнения сохраняются в экземпляре TaskInfo и добавляются в список задач.

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

StopWatch timeMeasure = new StopWatch();

timeMeasure.start("Task 1");
Thread.sleep(1000);
timeMeasure.stop();

System.out.println("Last task time in Millis: " 
             + timeMeasure.getLastTaskMillis());

Результат:

Last task time in Millis: 1009

Вы можете получить доступ к сумме всех задач с помощью функций getTotalTimeSeconds(), getTotalTimeMillis() и getTotalTimeNanos().

Вы также можете получить доступ к последней задаче StopWatch через getLastTaskInfo(), который выводит экземпляр TaskInfo. Этот экземпляр содержит информацию о последней задаче, например, имя и сколько времени она заняла в секундах, миллисекундах и наносекундах:

StopWatch stopWatch = new StopWatch();

stopWatch.start("Task 1");
Thread.sleep(1000);
stopWatch.stop();

System.out.println(stopWatch.getLastTaskInfo().getTaskName());

System.out.println(stopWatch.getLastTaskInfo().getTimeMillis());

Результат:

Task 1
1008

При решении нескольких задач удобно использовать метод prettyPrint(), который печатает все записи в табличном виде с простым форматированием:

StopWatch stopWatch = new StopWatch("Measure Code Execution");
    
stopWatch.start("1. Task");
Thread.sleep(2000);
stopWatch.stop();
    
stopWatch.start("2. Task");
Thread.sleep(5000);
stopWatch.stop();
 
stopWatch.start("3. Task");
Thread.sleep(3000);
stopWatch.stop();
  
System.out.println(stopWatch.prettyPrint());

Вывод:

StopWatch 'Measure Code Execution': running time = 10012348500 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
2002729600  020%  1. Task
5006985700  050%  2. Task
3002633200  030%  3. Task

Примечание: если мы используем секундомер для измерения времени выполнения кода для большого количества интервалов (порядка сотен тысяч или миллионов) – список TaskInfo займёт значительную часть вашей памяти. Вы можете отключить его так:

stopWatch.setKeepTaskList(false);

Заключение

В этом уроке мы рассмотрели класс утилиты StopWatch – ответ Spring на отсутствие инструментов измерения времени в Java.

Ответить