Каков стандартный способ профилирования вызовов методов Scala?
Что мне нужно, так это крючки вокруг метода, с помощью которых я могу запускать и останавливать таймеры.
В Java я использую аспектное программирование, aspectJ, для определения методов, которые нужно профилировать, и внедрения байт-кода для достижения того же.
Есть ли более естественный способ в Scala, где я могу определить набор функций, которые будут вызываться до и после функции, без потери статической типизации в процессе?
Ответы:
Вы хотите сделать это, не меняя код, для которого вы хотите измерять время? Если вы не против изменить код, вы можете сделать что-то вроде этого:
источник
t1
в рамкахfinally
предложенияdef time[R](label: String)(block: => R): R = {
затем добавьте этикетку кprintln
В дополнение к ответу Джеспера вы можете автоматически переносить вызовы методов в REPL:
А теперь - обернем что-нибудь в это
ОК - нам нужно быть в режиме питания
Завернуть
Понятия не имею, почему это напечатано 5 раз
Обновление от 2.12.2:
источник
:wrap
функция была удалена из REPL: - \Есть три бенчмаркинга библиотеки для Scala , которые вы можете воспользоваться.
Поскольку URL-адреса на связанном сайте могут измениться, я вставляю соответствующее содержимое ниже.
SPerformance - среда тестирования производительности, предназначенная для автоматического сравнения тестов производительности и работа внутри Simple Build Tool.
scala-benchmarking-template - проект шаблона SBT для создания (микро) тестов Scala на основе Caliper.
Метрики - получение метрик на уровне JVM и приложений. Итак, вы знаете, что происходит
источник
Вот что я использую:
источник
testing.Benchmark
может быть полезно.источник
Я взял решение у Джеспера и добавил к нему некоторую агрегацию при многократном запуске одного и того же кода.
Предположим, вы хотите синхронизировать две функции,
counter_new
иcounter_old
следующее их использование:Надеюсь, это будет полезно
источник
Я использую технику, которую легко перемещать в блоках кода. Суть в том, что одна и та же строка запускает и заканчивает таймер, так что это действительно простое копирование и вставка. Еще одна приятная вещь заключается в том, что вы можете определить, что для вас значит время, в виде строки, и все это в одной строке.
Пример использования:
Код:
Плюсы:
Минусы:
источник
Timelog.timer("timer name/description")
:?ScalaMeter - хорошая библиотека для тестирования производительности в Scala.
Ниже простой пример
Если вы выполните приведенный выше фрагмент кода в Scala Worksheet, вы получите время выполнения в миллисекундах.
источник
Мне нравится простота ответа @wrick, но я также хотел:
профилировщик обрабатывает цикл (для единообразия и удобства)
более точное время (с помощью nanoTime)
время на итерацию (не общее время всех итераций)
просто верните ns / итерацию - не кортеж
Это достигается здесь:
Для еще большей точности простая модификация позволяет создать цикл разогрева JVM Hotspot (не рассчитанный по времени) для синхронизации небольших фрагментов:
источник
Рекомендуемый подход к тестированию кода Scala - через sbt-jmh.
Этот подход используется во многих крупных проектах Scala, например,
Простая обертка таймер на основе
System.nanoTime
является не надежным методом бенчмаркинг:Кроме того, такие соображения, как разминка JIT , сборка мусора, общесистемные события и т. Д., Могут внести непредсказуемость в измерения:
Основываясь на ответе Трэвиса Брауна, вот пример того, как настроить тест JMH для Scala.
project/plugins.sbt
build.sbt
добавить в
src/main/scala/bench/VectorAppendVsListPreppendAndReverse.scala
Результаты
который, кажется, указывает, что добавление к a,
List
а затем обратное его изменение в конце на порядок быстрее, чем продолжение добавления к aVector
.источник
Стоя на плечах гигантов ...
Более идеальной была бы надежная сторонняя библиотека, но если вам нужно что-то быстрое и основанное на стандартной библиотеке, следующий вариант предоставляет:
,
Также стоит отметить, что вы можете использовать этот
Duration.toCoarsest
метод для преобразования в максимально возможную единицу времени, хотя я не уверен, насколько это удобно с небольшой разницей во времени между запусками, напримеристочник
Вы можете использовать
System.currentTimeMillis
:Использование:
nanoTime покажет вам
ns
, что будет трудно увидеть. Поэтому я предлагаю вам использовать вместо него currentTimeMillis.источник