Как профилировать методы в Scala? - PullRequest
113 голосов
/ 06 февраля 2012

Что такое стандартный способ профилирования вызовов методов Scala?

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

В Java я использую аспектное программирование aspectJ, чтобы определить методы, которые нужно профилировать, и внедрить байт-код для достижения того же.

Есть ли более естественный способ в Scala, где я могу определить набор функций, которые будут вызываться до и после функции, без потери статической типизации в процессе?

Ответы [ 11 ]

1 голос
/ 17 февраля 2016

Стоя на плечах великанов ...

Надежная сторонняя библиотека была бы более идеальной, но если вам нужно что-то быстрое и основанное на std-библиотеках, следующий вариант обеспечивает:

  • Повторы
  • Последний результат выигрывает для нескольких повторений
  • Общее время и среднее время для многократных повторений
  • Устраняет необходимость использования времени / мгновенного провайдера в качестве параметра

.

import scala.concurrent.duration._
import scala.language.{postfixOps, implicitConversions}

package object profile {

  def profile[R](code: => R): R = profileR(1)(code)

  def profileR[R](repeat: Int)(code: => R): R = {
    require(repeat > 0, "Profile: at least 1 repetition required")

    val start = Deadline.now

    val result = (1 until repeat).foldLeft(code) { (_: R, _: Int) => code }

    val end = Deadline.now

    val elapsed = ((end - start) / repeat)

    if (repeat > 1) {
      println(s"Elapsed time: $elapsed averaged over $repeat repetitions; Total elapsed time")

      val totalElapsed = (end - start)

      println(s"Total elapsed time: $totalElapsed")
    }
    else println(s"Elapsed time: $elapsed")

    result
  }
}

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

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.concurrent.duration._
import scala.concurrent.duration._

scala> import scala.language.{postfixOps, implicitConversions}
import scala.language.{postfixOps, implicitConversions}

scala> 1000.millis
res0: scala.concurrent.duration.FiniteDuration = 1000 milliseconds

scala> 1000.millis.toCoarsest
res1: scala.concurrent.duration.Duration = 1 second

scala> 1001.millis.toCoarsest
res2: scala.concurrent.duration.Duration = 1001 milliseconds

scala> 
...