benchmarking a function that returns an unlifted type

Apologies for a newbie question, but I am seeking advice on how to benchmark a pure function that returns an unlifted type. I've heard tell that `criterion` is good for benchmarking, and so I'm using that library (but have no particular allegiance to it, if something else is better). Specifically, I'm comparing a function over unlifted types with the same function written over lifted types, trying to observe how much we pay for the boxing/unboxing. To benchmark the lifted version, I just use criterion's whnf function. That seems to be working splendidly. Of course, whnf doesn't work over unlifted types, so I found its source code and inlined it. This compiles. But it doesn't work! No matter what I do, the unlifted version measures in the nanoseconds. I'm guessing that GHC "cleverly" is avoiding recomputation. How can I stop this? Here is my code:
main :: IO () main = do initializeTime let lifted = whnf fastSumPrimes 100000
unlifted = Benchmarkable go where go n | n <= 0 = return () | otherwise = let x = fastSumPrimes# 100000# in go (n-1)
benchmark lifted benchmark unlifted
I've tried increasing the argument in the unlifted case, to no avail. I've also tried using `case` instead of `let`. -ddump-simpl suggests that fastSumPrimes# is really being called, but I'm dubious. Can anyone offer advice? Thanks! Richard

Won't boxing at the end work, that should have only single unboxing/boxing action: unlifted = whnf (\Int# n -> Int# (fastSumPrimes# n)) 100000 - Oleg On 18.03.2017 19:32, Richard Eisenberg wrote:
Apologies for a newbie question, but I am seeking advice on how to benchmark a pure function that returns an unlifted type. I've heard tell that `criterion` is good for benchmarking, and so I'm using that library (but have no particular allegiance to it, if something else is better).
Specifically, I'm comparing a function over unlifted types with the same function written over lifted types, trying to observe how much we pay for the boxing/unboxing. To benchmark the lifted version, I just use criterion's whnf function. That seems to be working splendidly. Of course, whnf doesn't work over unlifted types, so I found its source code and inlined it. This compiles. But it doesn't work! No matter what I do, the unlifted version measures in the nanoseconds. I'm guessing that GHC "cleverly" is avoiding recomputation. How can I stop this?
Here is my code:
main :: IO () main = do initializeTime let lifted = whnf fastSumPrimes 100000
unlifted = Benchmarkable go where go n | n <= 0 = return () | otherwise = let x = fastSumPrimes# 100000# in go (n-1)
benchmark lifted benchmark unlifted I've tried increasing the argument in the unlifted case, to no avail. I've also tried using `case` instead of `let`. -ddump-simpl suggests that fastSumPrimes# is really being called, but I'm dubious.
Can anyone offer advice?
Thanks! Richard _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (2)
-
Oleg Grenrus
-
Richard Eisenberg