9
votes

I need to measure CPU time of a function like following:

t <- getCPUTime
res <- callTheFunction input
t' <- getCPUTime
print $ t' - t

The problem comes from the laziness of Haskell. callTheFunction must be strictly evaluated. I've searched a lot and tried to use seq and $! but without success. I think this should be a quite common task. Anyway, I need some help. Thanks.

Update: Thanks for all the help, especially @FUZxxl. It reminds me the difference between WHNF (Weak Head Normal Form) and Normal Form. Haskell/Laziness helps understand the lazy evaluation of Haskell.

What I needed is one more step evaluation. Anyway $! or evaluate both works as long as only WHNF is needed for res:

t <- getCPUTime
res <- callTheFunction input
evaluate res  OR  return $! res
t' <- getCPUTime
print $ t' - t
3
This doesn't fix your strictness issue at all (use evaluate for that) but for the quick-and-dirty timings (i.e. simpler than criterion) you can just use the timeIt package: hackage.haskell.org/package/timeitsclv

3 Answers

8
votes

If you're benchmarking then you should use Criterion. Otherwise use NFData (rnf) and bang patterns to force evaluation.

7
votes

Use the function evaluate :: a -> IO a from Control.Exception. It evaluates its argument to WHNF when the corresponding IO-action is executed. You have to make sure that WHNF is sufficient for your function though.

4
votes

If you are trying to do benchmarks please use the excellent criterion library, which is on Hackage.