In the post ‘Forcing evaluation in Haskell‘ , I described how to fully evaluate a value to get around Haskell’s lazy evaluation. Since then, I’ve found myself using the following snippet a lot:
import Control.Parallel.Strategies import Test.BenchPress bench 1 . print . rnf
This snippet fully evaluates a value and prints how long it took to do so. I regularly use it on the Programming Praxis problems to see where the bottleneck lies in my algorithm. It has the minor annoyance, however, that it prints a lot of information (min, max, mean, median, percentiles) that is all identical, because I only run it once. The reason I only run it once is that I’m typically evaluating a pure value, which means that any subsequent attempts to benchmark the evaluation time will take no time at all, since it has already been evaluated.
To solve this, I decided to write a small library to make this process easier and only print the time taken once. The result is StrictBench. A short example:
import Test.StrictBench main = bench [1..10000000 :: Integer]
This code would give
as output. For the rest of the documentation I refer you to the Hackage page. The source code is pretty simple:
module Test.StrictBench (bench, benchDesc, time) where import Control.Parallel.Strategies import Test.BenchPress hiding (bench) import Text.Printf bench :: NFData a => a -> IO () bench = (putStrLn . (++ " ms") . show =<<) . time benchDesc :: NFData a => String -> a -> IO () benchDesc s = (putStrLn . printf "%s: %s ms" s . show =<<) . time time :: NFData a => a -> IO Double time = fmap (median . fst) . benchmark 1 (return ()) (const $ return ()) . const . putStr . (`seq` "") . rnf
Nothing complicated, but a nice convenience library that I’ll be using from now on.