132 votes

Comment profiler les méthodes dans Scala?

Quel est le moyen standard de profiler les appels de méthode Scala?

Ce dont j'ai besoin, ce sont des crochets autour d'une méthode, que je peux utiliser pour démarrer et arrêter des minuteries.

En Java, j’utilise la programmation aspect, aspectJ, pour définir les méthodes à profiler et injecter du bytecode afin d’obtenir les mêmes résultats.

Existe-t-il une méthode plus naturelle dans Scala, dans laquelle je peux définir un ensemble de fonctions à appeler avant et après une fonction sans perdre de typage statique dans le processus?

234voto

Jesper Points 65733

Voulez-vous faire cela sans changer le code pour lequel vous voulez mesurer les timings? Si cela ne vous dérange pas de changer le code, vous pouvez faire quelque chose comme ceci:

 def time[R](block: => R): R = {
    val t0 = System.nanoTime()
    val result = block    // call-by-name
    val t1 = System.nanoTime()
    println("Elapsed time: " + (t1 - t0) + "ns")
    result
}

// Now wrap your method calls, for example change this...
val result = 1 to 1000 sum

// ... into this
val result = time { 1 to 1000 sum }
 

35voto

oxbow_lakes Points 70013

En plus de la réponse de Jesper, vous pouvez encapsuler automatiquement les invocations de méthodes dans le REPL:

 scala> def time[R](block: => R): R = {
   | val t0 = System.nanoTime()
   | val result = block
   | println("Elapsed time: " + (System.nanoTime - t0) + "ns")
   | result
   | }
time: [R](block: => R)R
 

Maintenant, passons à autre chose

 scala> :wrap time
wrap: no such command.  Type :help for help.
 

OK - nous devons être en mode puissance

 scala> :power
** Power User mode enabled - BEEP BOOP SPIZ **
** :phase has been set to 'typer'.          **
** scala.tools.nsc._ has been imported      **
** global._ and definitions._ also imported **
** Try  :help,  vals.<tab>,  power.<tab>    **
 

Envelopper

 scala> :wrap time
Set wrapper to 'time'

scala> BigDecimal("1.456")
Elapsed time: 950874ns
Elapsed time: 870589ns
Elapsed time: 902654ns
Elapsed time: 898372ns
Elapsed time: 1690250ns
res0: scala.math.BigDecimal = 1.456
 

Je ne sais pas pourquoi ces trucs imprimés sont sortis 5 fois

28voto

wrick Points 1825

C'est ce que j'utilise:

 import System.{currentTimeMillis => _time}
def profile[R](code: => R, t: Long = _time) = (code, _time - t)

// usage:
val (result, time) = profile { /* block of code to be profiled*/ }

val (result2, time2) = profile methodToBeProfiled(foo)
 

25voto

missingfaktor Points 44003

Il y a trois benchmarking des bibliothèques pour la Scala que vous pouvez profiter de.

Depuis l'Url du site lié et sont susceptibles de changer, je suis en collant le contenu pertinent ci-dessous.

  1. SPerformance - Tests de Performance du cadre visant à automagiquement comparant les essais de performance et de travail à l'intérieur de Simple Outil de construction.

  2. scala-benchmarking-modèle - SBT projet de modèle pour la création de Scala (micro-)repères fondés sur l'Étrier.

  3. Métriques - la Capture de la JVM et les applications de mesure de niveau. Donc, vous savez ce qu'il se passe

6voto

Luigi Plinge Points 23552

testing.Benchmark pourrait être utile.

 scala> def testMethod {Thread.sleep(100)}
testMethod: Unit

scala> object Test extends testing.Benchmark {
     |   def run = testMethod
     | }
defined module Test

scala> Test.main(Array("5"))
$line16.$read$$iw$$iw$Test$     100     100     100     100     100
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X