Допустим ли сравнительный анализ секундомера?
Кто-нибудь когда-нибудь использовал бенчмаркинг секундомеров, или всегда следует использовать инструмент повышения производительности? Есть ли хорошие бесплатные инструменты для Java? Какие инструменты вы используете?
Чтобы прояснить мои опасения, сравнительный анализ секундомера может быть ошибочным из-за планирования операционной системы. При заданном запуске вашей программы ОС может запланировать другой процесс (или несколько) в середине функции, которую вы синхронизируете. В Java дела обстоят даже немного хуже, если вы пытаетесь рассчитать время для многопоточного приложения, так как планировщик JVM добавляет даже немного больше случайности в микс.
Как вы относитесь к планированию операционной системы при тестировании?
13 ответов
Тестирование секундомера хорошо, если вы измеряете достаточно итераций, чтобы иметь смысл. Как правило, мне требуется общее прошедшее время, равное некоторому числу секунд, состоящих из одной цифры. В противном случае ваши результаты легко значительно искажаются при планировании и других прерываниях операций в вашем процессе.
Для этого я использую небольшой набор статических методов, которые я построил давным-давно, которые основаны на System.currentTimeMillis()
,
Для профилирования я несколько лет использовал jProfiler и нашел его очень хорошим. Недавно я просмотрел YourKit, который выглядит великолепно с веб- сайта, но я не использовал его вообще, лично.
Чтобы ответить на вопрос о прерываниях по расписанию, я обнаружил, что выполнение повторных прогонов до достижения согласованности / наблюдаемые работы на практике позволяют отсеять аномальные результаты планирования процессов. Я также обнаружил, что планирование потоков не оказывает практического влияния на периоды от 5 до 30 секунд. Наконец, после того, как вы пройдете, пороговое планирование в несколько секунд, по моему опыту, окажет незначительное влияние на результаты - я обнаружил, что 5-секундный прогон последовательно усредняет то же, что и 5-минутный прогон для времени / итерации.
Возможно, вы также захотите предварительно прогнать протестированный код около 10000 раз, чтобы "прогреть" JIT, в зависимости от того, сколько раз вы ожидаете, что тестируемый код будет выполняться с течением времени в реальной жизни.
Это полностью верно, если вы измеряете достаточно большие интервалы времени. Я бы выполнил 20-30 прогонов того, что вы намеревались протестировать, чтобы общее прошедшее время превысило 1 секунду. Я заметил, что вычисления времени, основанные на System.currentTimeMillis(), имеют тенденцию быть 0 мс или ~30 мс; Я не думаю, что вы можете получить что-то более точное, чем это. Вы можете попробовать System.nanoTime(), если вам действительно нужно измерить небольшой интервал времени:
- документация: http://java.sun.com/javase/6/docs/api/java/lang/System.html
- Так что вопрос об измерении небольших промежутков времени, так как System.nanoTime() также имеет некоторые проблемы: Как я могу измерять время с точностью до микросекунды в Java?
Секундомер на самом деле лучший эталон!
Реальное время отклика конечного пользователя - это время, которое действительно имеет значение.
Не всегда возможно получить это время с использованием доступных инструментов, например, большинство инструментов тестирования не включают время, необходимое браузеру для отображения страницы, поэтому на слишком сложной странице с плохо написанным CSS будет показано время отклика менее секунды инструменты, но 5 секунд плюс время отклика для пользователя.
Инструменты отлично подходят для автоматического тестирования и определения проблем, но не упускайте из виду то, что вы действительно хотите измерить.
Профилировщик дает вам более подробную информацию, которая может помочь в диагностике и устранении проблем с перфорированием.
С точки зрения фактического измерения, время секундомера - это то, что замечают пользователи, поэтому, если вы хотите проверить, что все находится в допустимых пределах, время секундомера вполне подойдет.
Однако, если вы действительно хотите решить проблемы, профилировщик может быть очень полезным.
Вам необходимо протестировать реалистичное количество итераций, поскольку вы получите разные ответы в зависимости от того, как вы тестируете время. Если вы выполняете операцию только один раз, это может ввести в заблуждение принятие среднего числа итераций. Если вы хотите узнать время, которое требуется после разогрева JVM, вы можете выполнить много (например, 10 000) итераций, которые не включены в тайминги.
Я также предлагаю вам использовать System.nanoTime(), так как он намного точнее. Если ваше тестовое время составляет около 10 микросекунд или меньше, вы не хотите вызывать это слишком часто, или это может изменить ваш результат. (Например, если я тестирую, скажем, 5 секунд, и я хочу знать, когда это произойдет, я получу nanoTime каждые 1000 итераций, если я знаю, что итерация очень быстрая)
Профилировщики могут мешать таймингу, поэтому я бы использовал комбинацию секундомера, чтобы определить общие проблемы с производительностью, а затем использовал профилировщик, чтобы определить, на что тратится время. Повторите по мере необходимости.
Как вы относитесь к планированию операционной системы при тестировании?
Эталон достаточно долго для системы, которая является представителем машины, которую вы будете использовать. Если ваша ОС замедляет работу вашего приложения, то это должно быть частью результата.
Нет смысла говорить, что моя программа была бы быстрее, если бы у меня не было ОС.
Если вы используете Linux
, вы можете использовать такие инструменты, как numactl
, chrt
а также taskset
контролировать, как используются процессоры и планирование.
В конце концов, это, пожалуй, вторая наиболее популярная форма бенчмаркинга, сразу после "бенчмаркинга без наблюдения", где мы говорим: "эта активность кажется медленной, а та - быстрой".
Обычно наиболее важно оптимизировать то, что мешает работе пользователя, что чаще всего зависит от того, как часто вы выполняете действие, и от того, что происходит одновременно. Другие формы сравнительного анализа часто просто помогают сосредоточиться на них.
Сегодня я запустил программу, которая искала и собирала информацию из множества файлов dBase, ее запуск занял чуть более часа. Я взглянул на код, сделал обоснованное предположение о том, что является узким местом, внес незначительное улучшение в алгоритм и перезапустил программу, на этот раз она была завершена за 2,5 минуты. Мне не нужны были какие-то причудливые инструменты для профилирования или тесты, чтобы сказать, что новая версия была значительным улучшением. Если бы мне нужно было дополнительно оптимизировать время выполнения, я бы, вероятно, сделал бы более сложный анализ, но в этом не было необходимости. Я считаю, что такого рода "сравнительный анализ секундомера" является приемлемым решением во многих случаях, и использование более продвинутых инструментов на самом деле отнимает больше времени в этих случаях.
Я думаю, что ключевым вопросом является сложность и длительность операции.
Иногда я даже использую физические измерения секундомера, чтобы увидеть, что для вычислений требуются минуты, часы, дни или даже недели (я работаю с приложением, где время выполнения порядка нескольких дней не является неслыханным, даже если секунды и минуты наиболее распространенные промежутки времени).
Однако автоматизация, предоставляемая вызовами любой системы часов на компьютере, например, вызов java миллис, упомянутый в связанной статье, явно лучше ручного наблюдения, как долго что-то работает.
Профилировщики хороши, когда они работают, но у меня были проблемы с применением их к нашему приложению, которое обычно включает в себя динамическую генерацию кода, динамическую загрузку DLL и работу, выполняемую на двух встроенных языках сценариев, скомпилированных как раз вовремя: мое заявление. Они довольно часто ограничиваются принятием единого исходного языка и другими нереалистичными ожиданиями для сложного программного обеспечения.
Я не думаю, что тестирование секундомера слишком ужасно, но если вы можете попасть на компьютер с ОС Solaris или OS X, вам стоит проверить DTrace. Я использовал его, чтобы получить отличную информацию о времени в моих приложениях.
Я делаю это все время. Я бы предпочел использовать профилировщик, но поставщик языка, специфичного для предметной области, с которым я работаю, его не предоставляет.
Я всегда использую бенчмаркинг секундомеров, так как это намного проще. Результаты не должны быть очень точными для меня, хотя. Если вам нужны точные результаты, вам не следует использовать тестирование секундомера.