Qu'est-ce qu'une méthode standard de profilage des 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 les minuteries.
En Java, j'utilise la programmation d'aspect, aspectJ, pour définir les méthodes à profiler et injecter du bytecode pour y parvenir.
Existe-t-il un moyen plus naturel dans Scala, où je peux définir un tas de fonctions à appeler avant et après une fonction sans perdre aucun typage statique dans le processus?
Réponses:
Voulez-vous faire cela sans changer le code pour lequel vous souhaitez mesurer les temps? Si cela ne vous dérange pas de changer le code, vous pouvez faire quelque chose comme ceci:
la source
t1
dans unefinally
clausedef time[R](label: String)(block: => R): R = {
puis ajoutez l'étiquette auprintln
En plus de la réponse de Jesper, vous pouvez automatiquement encapsuler les invocations de méthode dans le REPL:
Maintenant - enveloppons quoi que ce soit dans ce
OK - nous devons être en mode puissance
Envelopper
Je ne sais pas pourquoi ce truc imprimé 5 fois
Mise à jour à partir de la 2.12.2:
la source
:wrap
fonctionnalité a été supprimée de la REPL: - \Il existe trois bibliothèques d'analyse comparative pour Scala dont vous pouvez bénéficier.
Étant donné que les URL du site lié sont susceptibles de changer, je colle le contenu pertinent ci-dessous.
SPerformance - Cadre de test de performance visant à comparer automatiquement les tests de performance et à travailler dans Simple Build Tool.
scala-benchmarking-template - Projet de modèle SBT pour créer des (micro-) benchmarks Scala basés sur Caliper.
Métriques - Capture des métriques au niveau de la JVM et de l'application. Alors tu sais ce qui se passe
la source
C'est ce que j'utilise:
la source
testing.Benchmark
pourrait être utile.la source
J'ai pris la solution de Jesper et y ai ajouté une agrégation sur plusieurs exécutions du même code
Supposons que vous vouliez chronométrer deux fonctions
counter_new
etcounter_old
, ce qui suit est l'utilisation:Espérons que cela soit utile
la source
J'utilise une technique facile à déplacer dans les blocs de code. Le point crucial est que la même ligne exacte commence et termine la minuterie - il s'agit donc vraiment d'un simple copier-coller. L'autre chose intéressante est que vous pouvez définir ce que le timing signifie pour vous comme une chaîne, le tout dans la même ligne.
Exemple d'utilisation:
Le code:
Avantages:
Les inconvénients:
la source
Timelog.timer("timer name/description")
:?ScalaMeter est une belle bibliothèque pour effectuer des analyses comparatives dans Scala
Voici un exemple simple
Si vous exécutez l'extrait de code ci-dessus dans Scala Worksheet, vous obtenez le temps d'exécution en millisecondes
la source
J'aime la simplicité de la réponse de @ wrick, mais je voulais aussi:
le profileur gère le bouclage (par souci de cohérence et de commodité)
synchronisation plus précise (en utilisant nanoTime)
temps par itération (pas le temps total de toutes les itérations)
retourne simplement ns / itération - pas un tuple
Ceci est réalisé ici:
Pour encore plus de précision, une simple modification permet une boucle de préchauffage JVM Hotspot (non chronométrée) pour chronométrer de petits extraits:
la source
L'approche recommandée pour l'analyse comparative du code Scala est via sbt-jmh
Cette approche est adoptée par de nombreux grands projets Scala, par exemple,
Le minuteur de wrapper simple basé sur
System.nanoTime
n'est pas une méthode fiable d'analyse comparative:En outre, des considérations telles que le préchauffage JIT , le garbage collection, les événements à l'échelle du système, etc. peuvent introduire de l'imprévisibilité dans les mesures:
Basé sur la réponse de Travis Brown, voici un exemple de configuration du benchmark JMH pour Scala
project/plugins.sbt
build.sbt
Ajouter à
src/main/scala/bench/VectorAppendVsListPreppendAndReverse.scala
Les résultats sont
ce qui semble indiquer le préfixe à a
List
, puis l'inverser à la fin est d'un ordre de grandeur plus rapide que de continuer à ajouter à aVector
.la source
Tout en se tenant sur les épaules de géants ...
Une bibliothèque tierce solide serait plus idéale, mais si vous avez besoin de quelque chose de rapide et basé sur une bibliothèque std, la variante suivante fournit:
.
Il convient également de noter que vous pouvez utiliser la
Duration.toCoarsest
méthode pour convertir la plus grande unité de temps possible, bien que je ne sois pas sûr à quel point cela est convivial avec un décalage horaire mineur entre les exécutions, par exemplela source
Vous pouvez utiliser
System.currentTimeMillis
:Usage:
nanoTime vous montrera
ns
, donc il sera difficile de voir. Je suggère donc que vous puissiez utiliser currentTimeMillis à la place.la source