2010-06-14 10 views
40

Wiem, że mogę uzyskać czas potrzebny do oceny, że funkcja może zostać wydrukowana na ekranie/stdout przy użyciu funkcji czasu/makra.Jak testować funkcje w Clojure?

Makro czasowe zwraca wartość ocenianej funkcji, co sprawia, że ​​wspaniale jest ją używać w linii. Jednak chcę automatycznie mierzyć środowisko wykonawcze w określonych okolicznościach.

Czy istnieje funkcja, która zwraca czas, który upłynął w niektórych bibliotekach, aby pomóc w tej analizie porównawczej?

+0

możliwy duplikat [Narzędzia profilowania dla Clojure?] (Http://stackoverflow.com/questions/2974916/profiling-tool-for-clojure) –

+0

Nie sądzę, pytanie prejudycjalne jest o zewnętrznym benchmarkingu, to pytanie dotyczy raczej oprzyrządowania kodu. Muszę przyznać, że jestem zaskoczony, że ktoś szuka duplikatów w 5-letnich pytaniach. –

Odpowiedz

27

Możesz zajrzeć do biblioteki porównawczej Hugo Duncana dla Clojure - Criterium.

Od README:

środki Criterium czas obliczania wyrażenia. Został zaprojektowany w celu wyeliminowania niektórych pułapek testów porównawczych, a w szczególności testów porównawczych na maszynie JVM.

ten obejmuje:

  • statystycznej obróbki wielu oceny
  • włączenie wygrzany, mającego na celu kompilator JIT zoptymalizować kod
  • przedmuchiwania GC przed rozpoczęciem badania, w celu wyizolowania synchronizacją ze stanu GC przed badaniem
  • końcowe zmuszony GC po przeprowadzeniu badań w celu oszacowania wpływu oczyszczania od czasu powoduje
30

Jeśli chodzi tylko o programistyczne uchwycenie napisu, możesz powiązać * out * z czymś innym przed użyciem czasu.

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

Jeśli chcesz mieć większą kontrolę nad tym formacie, można stworzyć własną wersję czasie przy użyciu metod czasu systemowego Java, która jest co czas makro zastosowań pod maską anyway:

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__) 

Weź tę podstawową strukturę i zastąp połączenie pod numerem prn z dowolnym mechanizmem raportowania.

+4

+1 za używanie macroexpand do kopania pod maską! – mikera

+1

Dzięki, patrzyłem na to, aby zacząć od też. Biblioteka kryterium pasuje naprawdę do rachunku. Ale chyba, że ​​znasz bibliotekę Haskell, nie natkniesz się na nią przez przypadek, używając Google'a. –

+1

@PeterTillemans No cóż, jesteśmy, biorąc pod uwagę, że wspomniano o tym w StackOverflow. :-) –