Benchmarking scanl1 with Criterion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module Main where

import Criterion.Main
import System.Random

import Control.DeepSeq

main =
  defaultMain
    [ bench "Sum"   $ nf sum rand                  -- ~35 ms
    , bench "Sum'"  $ nf (last . scanl1 (+)) rand  -- same
    , bench "Scan"  $ nf (scanl1 (+)) rand         -- ~5 ms
    , bench "Scan'" $ nf (force . scanl1 (+)) rand -- ~15 ms
    ]
  where rand = force $ randomInts n
        n = 100000

randomInts n = take n r
  where r = randoms $ mkStdGen 1234 :: [Int]

Benchmarking scanl1 with Criterion (annotation)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{-# language BangPatterns #-}

module Main where

import Criterion.Main
import System.Random

import Control.DeepSeq

main = do
  defaultMain
    [ bench "Sum"   $ nf sum rand                  -- ~35 ms
    , bench "Sum'"  $ nf (last . scanl1 (+)) rand  -- same
    , bench "Scan"  $ nf (scanl1 (+)) rand         -- ~5 ms
    , bench "Scan'" $ nf (force . scanl1 (+)) rand -- ~15 ms
    ]
--  where !rand = force $ randomInts n -- use bang pattern to make sure rand is in normal form before bench mark.
  where rand = force $ randomInts n
        n = 100000

randomInts n = take n r
  where r = randoms $ mkStdGen 1234 :: [Int]
1:1: Error: Unused LANGUAGE pragma
Found:
{-# LANGUAGE BangPatterns #-}
Why not remove it.
10:8: Error: Redundant do
Found:
do defaultMain
[bench "Sum" $ nf sum rand,
bench "Sum'" $ nf (last . scanl1 (+)) rand,
bench "Scan" $ nf (scanl1 (+)) rand,
bench "Scan'" $ nf (force . scanl1 (+)) rand]
Why not:
defaultMain
[bench "Sum" $ nf sum rand,
bench "Sum'" $ nf (last . scanl1 (+)) rand,
bench "Scan" $ nf (scanl1 (+)) rand,
bench "Scan'" $ nf (force . scanl1 (+)) rand]