Тестирование производительности Java

Я хочу провести временные тесты для Java-приложения. Вот чем я сейчас занимаюсь:

long startTime = System.currentTimeMillis();
doSomething();
long finishTime = System.currentTimeMillis();
System.out.println("That took: " + (finishTime - startTime) + " ms");

Есть ли что-то «неправильное» в подобном тестировании производительности? Какой способ лучше?

Дубликат: Допустимо ли тестирование секундомера?

Вы спрашиваете, подходит ли бенчмаркинг с использованием секундомера, или вы спрашиваете, правильный ли это способ сделать это?

Bill the Lizard 15.01.2009 20:54

Я действительно хочу получить ответы на оба вопроса ... Но больше склоняюсь к "правильному способу сделать это для получения точных результатов"

mainstringargs 15.01.2009 20:56

Не по теме и действительно не решает вашу проблему, поэтому я вставлю это в комментарий. Выступление Джона Бентли в Google «Три красивых быстрых сортировки» - это действительно интересный взгляд на производительность и анализ алгоритмов. Веселая штука. video.google.com/videoplay?docid=-1031789501179533828

Todd 15.01.2009 21:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
51
3
66 741
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Я предполагаю, что вы тоже захотите сделать Something () до того, как начнете отсчет времени, чтобы код был JITter и «разогретым».

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

Имейте в виду, что разрешение System.currentTimeMillis() зависит от операционной системы. Я считаю, что Windows составляет около 15 мсек. Поэтому, если ваш doSomething() работает быстрее, чем разрешение по времени, вы получите дельту 0. Вы можете запускать doSomething() в цикле несколько раз, но тогда JVM может его оптимизировать.

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

Ответ принят как подходящий

Единственный недостаток этого подхода заключается в том, что время, необходимое doSomething() для выполнения в «реальном» времени, может сильно различаться в зависимости от того, какие другие программы работают в системе и какова их нагрузка. Это делает измерение производительности несколько неточным.

Еще один точный способ отслеживания времени, необходимого для выполнения кода, при условии, что код является однопоточным, - это посмотреть на процессорное время, потребляемое потоком во время вызова. Вы можете сделать это с помощью классов JMX; в частности, с ThreadMXBean. Вы можете получить экземпляр ThreadMXBean из java.lang.management.ManagementFactory, и, если ваша платформа поддерживает его (большинство из них поддерживает), используйте метод getCurrentThreadCpuTime вместо System.currentTimeMillis для проведения аналогичного теста. Имейте в виду, что getCurrentThreadCpuTime сообщает время в наносекундах, а не в миллисекундах.

Вот пример метода (Scala), который можно использовать для измерения:

def measureCpuTime(f: => Unit): java.time.Duration = {

  import java.lang.management.ManagementFactory.getThreadMXBean
  if (!getThreadMXBean.isThreadCpuTimeSupported)
    throw new UnsupportedOperationException(
      "JVM does not support measuring thread CPU-time")

  var finalCpuTime: Option[Long] = None
  val thread = new Thread {
    override def run(): Unit = {
      f
      finalCpuTime = Some(getThreadMXBean.getThreadCpuTime(
        Thread.currentThread.getId))
    }
  }
  thread.start()

  while (finalCpuTime.isEmpty && thread.isAlive) {
    Thread.sleep(100)
  }

  java.time.Duration.ofNanos(finalCpuTime.getOrElse {
    throw new Exception("Operation never returned, and the thread is dead " +
      "(perhaps an unhandled exception occurred)")
  })
}

(Не стесняйтесь переводить вышесказанное на Java!)

Эта стратегия не идеальна, но она менее подвержена изменениям в загрузке системы.

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

Noctis Skytower 28.06.2016 17:49

@NoctisSkytower, я добавил образец кода (метод измерения). К сожалению (или к счастью?) Это на Scala; не стесняйтесь переводить и редактировать ответ.

Chris W. 26.10.2017 00:30

@ Даан ссылка не работает.

Abhyudaya Sharma 11.03.2019 18:59

Вы смотрели инструменты профилирования в netbeans и затмение. Эти инструменты помогут вам лучше понять, что ДЕЙСТВИТЕЛЬНО занимает все время в вашем коде. Я обнаружил проблемы, которых не осознавал, используя эти инструменты.

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

Ссылка, должно быть, переехала. Japex сейчас находится по адресу: japex.java.net

charmoniumQ 04.09.2015 20:29

Код, показанный в вопросе, не является хорошим кодом для измерения производительности:

  1. Компилятор может оптимизировать ваш код, изменив порядок операторов. Да, он может это сделать. Это означает, что весь ваш тест может провалиться. Он даже может выбрать встроенный тестируемый метод и переупорядочить операторы измерения во встроенном коде.

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

  3. Даже если предположить, что компилятор / точка доступа не обманули вас, вы измеряете «время стены». Что вы должны измерять, так это процессорное время (если вы не используете ресурсы ОС и не хотите их также включать или вы не измеряете оспаривание блокировок в многопоточной среде).

Решение? Используйте настоящий профайлер. Есть много чего, как бесплатные профилировщики, так и демонстрации / ограниченные по времени испытания сильных рекламных роликов.

Hotspot не только скомпилирует код в какой-то момент и произведет оптимизацию, о которой вы упомянули, но и на самом деле может иметь MUTLITPLE попытки компиляции с разными оптимизациями: т.е. повторения по времени могут означать синхронизацию другого кода! Будьте очень-очень-очень осторожны ...

Neil Coffey 15.01.2009 23:32

Не хотелось предлагать какие-либо варианты профилировщика?

John R Perry 20.09.2018 03:23

@JohnRPerry, поскольку список часто меняется, а те, которые мне нравятся, могут не соответствовать вашим потребностям, безопасно просто загуглить профилировщики Java и выяснить это самостоятельно. Лично мне нравится работать с YourKit для профилирования тяжелого веса и Java Microbenchmark Harness (JMH) для микротестов.

Ran Biron 22.02.2019 22:50

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

Я предлагаю вам ДЖЕНСОР, Java Profiler с открытым исходным кодом, за его простоту использования и отсутствие накладных расходов на процессор. Вы можете скачать его, обработать код и получить всю необходимую информацию о вашем коде.

Вы можете скачать его по ссылке: http://jensor.sourceforge.net /

Другие вопросы по теме