I am benchmarking insertion sort on worst case input (reverse ordered list) and random input.
import Control.Monad
import Data.List
import System.Random
import Control.Exception
import Control.DeepSeq
import Criterion.Main
--- Sorting ---
insertionSort :: (Ord a) => [a] -> [a]
insertionSort [] = []
insertionSort (x:xs) = x `insert` (sort xs)
--- Generators ---
worstCaseGen :: Int -> [Int]
worstCaseGen n = [n, n-1..1]
bestCaseGen :: Int -> [Int]
bestCaseGen n = [1..n]
randomGen :: Int -> StdGen -> [Int]
randomGen n = take n . randoms
--- Testing ---
main = do
gen <- newStdGen
randomList <- evaluate $ force $ randomGen 10000 gen
defaultMain [
bgroup "Insertion Sort" [ bench "worst" $ nf insertionSort (worstCaseGen 10000)
, bench "best" $ nf insertionSort (bestCaseGen 10000)
, bench "gen" $ nf last randomList
, bench "random" $ nf insertionSort randomList
]
]
While random input should perform at about the same magnitude as the worst case input, in reality the benchmark shows that it is about 20 times slower. My guess is that branch prediction kicks in and the random case is very hard to predict and thus becomes slower. Could this be true?
This is my .cabal if it helps:
executable BranchPrediction
main-is: Main.hs
build-depends: base >=4.12 && <4.13,
random,
criterion ==1.5.4.0,
deepseq ==1.4.4.0
default-language: Haskell2010