Dies ist auch eine etwas nuancierte Situation, da Funktionen in Haskell nicht vollständig "ausgeführt" werden müssen. Sie müssen nur für den gewünschten Wert ausreichend erweitert werden. Betrachten Sie head [1..], welches das erste Element einer unendlichen Liste nimmt.
Gatoatigrado
@gatoatigrado Deshalb hat das Kriterium die whnfund nfFunktionen.
Alternative
Antworten:
109
Einfachstes Dinge einfach zu tun , :set +sin ghci, und dann können Sie die Ausführungszeit alles , was Sie ausführen, zusammen mit der Speichernutzung sehen.
Funktionen laufen in ghci jedoch viel langsamer. In meinem Test etwa 10 mal langsamer.
Ray
3
Ist es möglich, die Genauigkeit der gemessenen Zeit wie in Millisekunden einzustellen?
SiXoS
1
Langsamer, ja, aber dies scheint sehr wertvoll zu sein, um Unterschiede im Zeit- und Raumverbrauch zwischen Algorithmen aufzuzeigen. Zum Beispiel <pre> <code> slow_fib :: Int -> Integer slow_fib 0 = 0 slow_fib 1 = 1 slow_fib n = slow_fib (n-2) + slow_fib (n-1) - vs. memoized_fib :: Int -> Integer memoized_fib = (map fib [0 ..] !!) wobei fib 0 = 0 fib 1 = 1 fib n = memoized_fib (n-2) + memoized_fib (n-1) </ pre> </ code> Wo Sie sehen können Die erste Funktion nimmt nicht nur viel mehr Zeit in Anspruch, sondern auch mehrere Größenordnungen mehr Platz.
Dies wird nicht mehr unterstützt - scheint veraltet zu sein.
Chris Stryczynski
3
Kriterium ist die ausgefeilteste Methode, obwohl ich es schwierig fand, sie zu starten, und sie scheint auf Benchmarking-Programme ausgerichtet zu sein. Ich wollte den Ausführungszeitpunkt berechnen und diese Daten in meinem Programm verwenden, und es scheint diesen Bedarf nicht zu decken, zumindest ist dies nicht sofort ersichtlich.
TimeIt ist sehr einfach und macht das, was ich wollte, außer dass es reine Funktionen nicht gut handhabt. Die für eine reine Funktion zurückgegebene Zeit ist die Thunk Allocation Time (AFAIK), und selbst bei Verwendung von seq kann es schwierig sein, das zu bekommen, was Sie wollen.
Was für mich funktioniert, basiert auf TimeIt.
import System.TimeIt
timeItTPure :: (a -> ()) -> a -> IO (Double,a)
timeItTPure p a = timeItT $ p a `seq` return a
In timeItTPure pa ist p die Funktion, die für die Bewertung des Ergebnisses einer reinen Berechnung a verantwortlich ist, so tief wie nötig, um das gute Bewertungszeitpunkt zu erhalten. Vielleicht ist dies eine einfache Musterübereinstimmung, vielleicht zählt es die Länge einer Liste, vielleicht ist es die Folge jedes Elements in der Liste, vielleicht ist es eine Deepseq usw.
Die Verwendung von seq ist schwierig. Beachten Sie, dass die folgende Funktion nicht wie gewünscht ausgeführt wird. Haskell ist eine mysteriöse Sache.
head [1..]
, welches das erste Element einer unendlichen Liste nimmt.whnf
undnf
Funktionen.Antworten:
Einfachstes Dinge einfach zu tun ,
:set +s
inghci
, und dann können Sie die Ausführungszeit alles , was Sie ausführen, zusammen mit der Speichernutzung sehen.quelle
Das
criterion
Paket wurde speziell dafür entwickelt.quelle
Überprüfen Sie, ob http://hackage.haskell.org/package/timeit Ihren Anforderungen entspricht.
quelle
Der Benchmark für die Funktionsausführungszeit ist in Criterion.Measurement enthalten
Zum Beispiel, wenn ich die Zeit von erfassen möchte
someIOFunction :: IO ()
import Criterion.Measurement main = secs <$> time_ someIOFunction >>= print
quelle
Kriterium ist die ausgefeilteste Methode, obwohl ich es schwierig fand, sie zu starten, und sie scheint auf Benchmarking-Programme ausgerichtet zu sein. Ich wollte den Ausführungszeitpunkt berechnen und diese Daten in meinem Programm verwenden, und es scheint diesen Bedarf nicht zu decken, zumindest ist dies nicht sofort ersichtlich.
TimeIt ist sehr einfach und macht das, was ich wollte, außer dass es reine Funktionen nicht gut handhabt. Die für eine reine Funktion zurückgegebene Zeit ist die Thunk Allocation Time (AFAIK), und selbst bei Verwendung von seq kann es schwierig sein, das zu bekommen, was Sie wollen.
Was für mich funktioniert, basiert auf TimeIt.
import System.TimeIt timeItTPure :: (a -> ()) -> a -> IO (Double,a) timeItTPure p a = timeItT $ p a `seq` return a
In timeItTPure pa ist p die Funktion, die für die Bewertung des Ergebnisses einer reinen Berechnung a verantwortlich ist, so tief wie nötig, um das gute Bewertungszeitpunkt zu erhalten. Vielleicht ist dies eine einfache Musterübereinstimmung, vielleicht zählt es die Länge einer Liste, vielleicht ist es die Folge jedes Elements in der Liste, vielleicht ist es eine Deepseq usw.
Die Verwendung von seq ist schwierig. Beachten Sie, dass die folgende Funktion nicht wie gewünscht ausgeführt wird. Haskell ist eine mysteriöse Sache.
badTimeItTPure a = timeItT . return $ seq (p a) a
quelle
https://github.com/chrissound/FuckItTimer
start' <- start timerc start' "begin" print "hello" timerc start' "after printing hello" benchmark timerc start' "end" end <- getVals start' forM_ (timert end) putStrLn
Ausgänge:
"hello" begin -> after printing hello: 0.000039555s after printing hello -> end: 1.333936928s
Dies scheint für meinen sehr einfachen Anwendungsfall gut zu funktionieren.
quelle