Skip to content

Instantly share code, notes, and snippets.

@meooow25
Last active August 19, 2022 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meooow25/b970d33913e05ec0925bdaef5f65d372 to your computer and use it in GitHub Desktop.
Save meooow25/b970d33913e05ec0925bdaef5f65d372 to your computer and use it in GitHub Desktop.
Haskell sort benchmarks, GHC 8.10.7, -O2, n=2e5

Sorting a list of length $2\cdot{10}^5$

[Int] [(Int, Int)]
Data.List.sort 246.3 ms 274.6 ms
Seq sort 169.8 ms 202.0 ms
IntMap sort 147.1 ms N/A
Map sort 269.9 ms
Unboxed vector sort 20.01 ms 34.96 ms
Custom unboxed mergesort 35.72 ms N/A
Custom boxed mergesort 106.1 ms
{-# LANGUAGE FlexibleContexts, QuantifiedConstraints, ScopedTypeVariables, TupleSections #-}
import Control.Monad
import Control.Monad.ST
import Data.Array.Base
import Data.Array.ST
import Criterion.Main
import Data.Foldable
import qualified Data.IntMap.Strict as IM
import qualified Data.List as L
import qualified Data.Map.Strict as M
import qualified Data.Sequence as Seq
import qualified Data.Vector.Algorithms.Intro as VA
import qualified Data.Vector.Unboxed as VU
main :: IO ()
main = defaultMain
[ env (pure testxs) $ \xs -> bgroup "[Int]"
[ bench "Data.List.sort" $ whnf (benchSort L.sort) xs
, bench "Seq sort" $ whnf (benchSort seqSort) xs
, bench "IntMap sort" $ whnf (benchSort intMapSort) xs
, bench "Vector sort" $ whnf (benchSort vecSort) xs
, bench "msortU" $ whnf (benchSort msortU) xs
]
, env (pure testys) $ \ys -> bgroup "[(Int, Int)]"
[ bench "Data.List.sort" $ whnf (benchSort L.sort) ys
, bench "Seq sort" $ whnf (benchSort seqSort) ys
, bench "Map sort" $ whnf (benchSort mapSort) ys
, bench "Vector sort" $ whnf (benchSort vecSort) ys
, bench "msort" $ whnf (benchSort msort) ys
]
, env (pure testxs) $ \xs -> bgroup "[Int] !! 100"
[ bench "Data.List.sort" $ whnf (benchSortIndex L.sort xs) 100
]
]
where
n = 200000
testxs = take n $ iterate ((`mod` 1000000007) . (*12345)) 1 :: [Int]
testys = zip testxs [1..] :: [(Int, Int)]
benchSort :: ([a] -> [a]) -> [a] -> Int
benchSort sortf xs = length (sortf xs)
{-# NOINLINE benchSort #-}
benchSortIndex :: ([a] -> [a]) -> [a] -> Int -> a
benchSortIndex sortf xs i = sortf xs !! i
{-# NOINLINE benchSortIndex #-}
seqSort :: Ord a => [a] -> [a]
seqSort = toList . Seq.unstableSort . Seq.fromList
intMapSort :: [Int] -> [Int]
intMapSort = IM.assocs . IM.fromListWith (+) . map (,1) >=> \(k, v) -> replicate v k
mapSort :: Ord a => [a] -> [a]
mapSort = M.assocs . M.fromListWith (+) . map (,1) >=> \(k, v) -> replicate v k
vecSort :: (VU.Unbox a, Ord a) => [a] -> [a]
vecSort xs = VU.toList $ VU.create $ do
v <- VU.thaw (VU.fromList xs)
VA.sort v
pure v
-- Merge sort implementations below from
-- https://github.com/meooow25/haccepted/blob/master/src/Sort.hs
msort :: Ord e => [e] -> [e]
msort = msortBy compare
msortBy :: (e -> e -> Ordering) -> [e] -> [e]
msortBy cmp xs = elems $ runSTArray $ do
a <- listArrayST (1, length xs) xs
mergeSort a cmp
pure a
msortU :: (Ord e, forall s. MArray (STUArray s) e (ST s), IArray UArray e) => [e] -> [e]
msortU = msortUBy compare
msortUBy :: (forall s. MArray (STUArray s) e (ST s), IArray UArray e)
=> (e -> e -> Ordering) -> [e] -> [e]
msortUBy cmp xs = elems $ runSTUArray $ do
a <- listUArrayST (1, length xs) xs
mergeSort a cmp
pure a
mergeSort :: forall a e m. (MArray a e m) => a Int e -> (e -> e -> Ordering) -> m ()
mergeSort a cmp = do
n <- getNumElements a
b :: a Int e <- newArray_ (1, n)
let merge l m r = foldM_ f (l, m) [l .. r-1] where
f (i, j) k
| i >= m = takej
| j >= r = takei
| otherwise = do
o <- cmp <$> unsafeRead a i <*> unsafeRead a j
if o /= GT then takei else takej
where
takei = (i + 1, j) <$ (unsafeWrite b k =<< unsafeRead a i)
takej = (i, j + 1) <$ (unsafeWrite b k =<< unsafeRead a j)
forM_ (takeWhile (<n) $ iterate (*2) 1) $ \w -> do
forM_ [0, 2*w .. n-1] $ \i -> merge i ((i + w) `min` n) ((i + 2*w) `min` n)
forM_ [0 .. n-1] $ \i -> unsafeRead b i >>= unsafeWrite a i
{-# INLINE mergeSort #-}
benchmarking [Int]/Data.List.sort
time 246.3 ms (243.3 ms .. 248.6 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 245.4 ms (244.0 ms .. 246.2 ms)
std dev 1.470 ms (565.1 μs .. 1.994 ms)
variance introduced by outliers: 16% (moderately inflated)
benchmarking [Int]/Seq sort
time 169.8 ms (168.5 ms .. 171.3 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 169.3 ms (168.0 ms .. 170.0 ms)
std dev 1.406 ms (296.6 μs .. 2.223 ms)
variance introduced by outliers: 12% (moderately inflated)
benchmarking [Int]/IntMap sort
time 147.1 ms (142.0 ms .. 151.5 ms)
0.999 R² (0.998 R² .. 1.000 R²)
mean 151.0 ms (148.8 ms .. 152.3 ms)
std dev 2.386 ms (1.172 ms .. 3.547 ms)
variance introduced by outliers: 12% (moderately inflated)
benchmarking [Int]/Vector sort
time 20.01 ms (19.87 ms .. 20.15 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 20.06 ms (19.92 ms .. 20.27 ms)
std dev 400.1 μs (206.8 μs .. 690.5 μs)
benchmarking [Int]/msortU
time 35.72 ms (35.41 ms .. 36.02 ms)
1.000 R² (0.999 R² .. 1.000 R²)
mean 36.23 ms (35.95 ms .. 36.61 ms)
std dev 720.7 μs (439.6 μs .. 1.028 ms)
benchmarking [(Int, Int)]/Data.List.sort
time 274.6 ms (269.9 ms .. 283.5 ms)
1.000 R² (0.998 R² .. 1.000 R²)
mean 274.2 ms (269.8 ms .. 277.1 ms)
std dev 4.678 ms (1.902 ms .. 6.714 ms)
variance introduced by outliers: 16% (moderately inflated)
benchmarking [(Int, Int)]/Seq sort
time 202.0 ms (192.3 ms .. 210.9 ms)
0.999 R² (0.997 R² .. 1.000 R²)
mean 195.8 ms (189.8 ms .. 200.4 ms)
std dev 7.304 ms (5.317 ms .. 9.629 ms)
variance introduced by outliers: 14% (moderately inflated)
benchmarking [(Int, Int)]/Map sort
time 269.9 ms (263.0 ms .. 278.0 ms)
1.000 R² (0.999 R² .. 1.000 R²)
mean 265.1 ms (256.4 ms .. 268.3 ms)
std dev 6.467 ms (1.108 ms .. 8.888 ms)
variance introduced by outliers: 16% (moderately inflated)
benchmarking [(Int, Int)]/Vector sort
time 34.96 ms (34.66 ms .. 35.29 ms)
1.000 R² (0.999 R² .. 1.000 R²)
mean 35.01 ms (34.55 ms .. 35.28 ms)
std dev 751.1 μs (401.6 μs .. 1.318 ms)
benchmarking [(Int, Int)]/msort
time 106.1 ms (102.2 ms .. 109.4 ms)
0.999 R² (0.997 R² .. 1.000 R²)
mean 114.4 ms (109.5 ms .. 128.5 ms)
std dev 14.15 ms (571.8 μs .. 22.53 ms)
variance introduced by outliers: 42% (moderately inflated)
benchmarking [Int] !! 100/Data.List.sort
time 15.26 ms (14.98 ms .. 15.60 ms)
0.998 R² (0.996 R² .. 0.999 R²)
mean 14.82 ms (14.58 ms .. 15.01 ms)
std dev 539.4 μs (406.9 μs .. 742.6 μs)
variance introduced by outliers: 11% (moderately inflated)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment