2010-06-14 5 views
40

Je sais que je peux obtenir le temps nécessaire pour évaluer une fonction qui peut être imprimée sur l'écran/stdout en utilisant la fonction temps/macro.Comment comparer les fonctions dans Clojure?

La macro de temps renvoie la valeur de la fonction évaluée, ce qui permet de l'utiliser en ligne. Cependant, je veux mesurer automatiquement le temps d'exécution dans des circonstances spécifiques.

Existe-t-il une fonction qui renvoie le temps écoulé dans une bibliothèque pour faciliter cette analyse comparative?

+0

duplication possible de [Outil de profilage pour Clojure?] (Http://stackoverflow.com/questions/2974916/profiling-tool-for-clojure) –

+0

Je ne pense pas, la question référée est À propos de l'analyse comparative externe, cette question concerne davantage l'instrumentation du code. Je dois admettre être surpris que quelqu'un cherche des doublons dans les questions de 5 ans. –

Répondre

27

Vous voudrez peut-être regarder dans la bibliothèque de benchmarking de Hugo Duncan pour Clojure - Criterium.

De l'README:

mesures Critérium le temps de calcul d'une expression. Il est conçu pour répondre à certains des pièges de l'analyse comparative et de l'analyse comparative de la JVM en particulier.

Cela comprend:

  • traitement statistique des multiples évaluations
  • inclusion d'une période d'échauffement, conçu pour permettre au compilateur JIT pour optimiser son code
  • purge de gc avant le test, pour isoler Timings de l'état GC avant le test
  • un GC forcé final après le test pour estimer l'impact du nettoyage sur les résultats de synchronisation
30

S'il ne s'agit que de capturer la chaîne par programme, vous pouvez lier * out * à autre chose avant d'utiliser time.

user=> (def x (with-out-str (time (+ 2 2)))) 
#'user/x 
user=> x 
"\"Elapsed time: 0.119 msecs\"\n" 

Si vous voulez plus de contrôle sur le format, vous pouvez créer votre propre version de temps en utilisant les méthodes de temps du système de Java, qui est ce que les temps utilisations macro sous le capot de toute façon:

user => (macroexpand '(time (+ 2 2))) 
(let* [start__4197__auto__ (. java.lang.System (clojure.core/nanoTime)) 
     ret__4198__auto__ (+ 2 2)] 
    (clojure.core/prn (clojure.core/str "Elapsed time: " (clojure.core//  
      (clojure.core/double 
       (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) 
           start__4197__auto__)) 1000000.0) " msecs")) 
ret__4198__auto__) 

Prenez cette structure de base et remplacez l'appel par prn avec le mécanisme de création de rapports que vous préférez.

+4

+1 pour l'utilisation de macroexpand pour creuser sous le capot! – mikera

+1

Merci, je regardais ça pour commencer aussi. La bibliothèque de critériums correspond vraiment à la facture. Mais à moins que vous ne connaissiez la bibliothèque Haskell, vous n'allez pas tomber dessus par hasard en utilisant google. –

+1

@PeterTillemans Eh bien, nous sommes maintenant, étant donné que cela est mentionné dans StackOverflow. :-) –

Questions connexes