Created
May 18, 2016 17:12
-
-
Save aavogt/2fac15d2a69e5a463522165d107af91a to your computer and use it in GitHub Desktop.
lexicographic sorting doesn't go faster when the sorting function sees more structure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Criterion.Main | |
import Criterion | |
import Data.List | |
import Data.Foldable (toList) | |
import Data.Random | |
import Data.Monoid ((<>)) | |
import qualified Data.IntMap as IM | |
import qualified Data.Map as M | |
import qualified Data.Sequence as S | |
import Control.DeepSeq | |
import Data.Ord | |
stagedSort :: [[a] -> [[a]]] -> [a] -> [a] | |
stagedSort (cmp : cmps) xs = stagedSort cmps =<< cmp xs | |
stagedSort [] xs = xs | |
data P = P !Char !Int | |
deriving (Eq,Ord) | |
instance NFData P where | |
rnf x = x `seq` () | |
main = do | |
let genNS = do | |
nsP <- sample $ shuffle [ P c n | c <- ['a' .. 'f'], | |
n <- take 100 $ cycle [0 .. 10]] | |
nsComma <- sample $ shuffle [ (c,n) | c <- ['a' .. 'f'], | |
n <- take 100 $ cycle [0 .. 10]] | |
return (nsP, nsComma) | |
defaultMain [bgroup "sorting P" | |
[env genNS $ \ ~(ns,_) -> bench "sortBy cmpSP" (nfElem (sortBy cmpSP) ns), | |
env genNS $ \ ~(ns,_) -> bench "sort" (nfElem sort ns), | |
env genNS $ \ ~(ns,_) -> bench "staged cmpSSP" (nfElem (stagedSort cmpSSP) ns)], | |
bgroup "sorting (,)" | |
[env genNS $ \ ~(_,ns) -> bench "sortBy cmpSC" (nfElem (sortBy cmpSC) ns), | |
env genNS $ \ ~(_,ns) -> bench "sort" (nfElem sort ns), | |
env genNS $ \ ~(_,ns) -> bench "staged cmpSSC" (nfElem (stagedSort cmpSSC) ns) | |
]] | |
{- Below, the SSP and SSC ought to be faster than the | |
finely tuned sort in the Data.List module, but they are not. | |
So the conclusion seems to be that we should continue to use | |
<> to create `a -> a -> Ordering` because exposing that | |
extra structure to this particular sorting algorithm (stagedSort) | |
doesn't help. | |
benchmarking sorting P/sortBy cmpSP | |
time 328.8 ?s (326.5 ?s .. 331.2 ?s) | |
0.999 R? (0.998 R? .. 1.000 R?) | |
mean 324.2 ?s (321.1 ?s .. 329.1 ?s) | |
std dev 12.41 ?s (9.198 ?s .. 20.02 ?s) | |
variance introduced by outliers: 33% (moderately inflated) | |
benchmarking sorting P/sort | |
time 318.4 ?s (317.5 ?s .. 319.2 ?s) | |
1.000 R? (0.999 R? .. 1.000 R?) | |
mean 324.5 ?s (321.9 ?s .. 329.9 ?s) | |
std dev 11.98 ?s (8.156 ?s .. 18.97 ?s) | |
variance introduced by outliers: 32% (moderately inflated) | |
benchmarking sorting P/staged cmpSSP | |
time 345.5 ?s (343.1 ?s .. 348.7 ?s) | |
0.999 R? (0.999 R? .. 1.000 R?) | |
mean 343.9 ?s (342.3 ?s .. 346.0 ?s) | |
std dev 6.379 ?s (4.829 ?s .. 8.261 ?s) | |
variance introduced by outliers: 10% (moderately inflated) | |
benchmarking sorting (,)/sortBy cmpSC | |
time 365.6 ?s (361.7 ?s .. 369.3 ?s) | |
0.999 R? (0.999 R? .. 1.000 R?) | |
mean 363.0 ?s (361.8 ?s .. 364.8 ?s) | |
std dev 5.261 ?s (4.028 ?s .. 7.015 ?s) | |
benchmarking sorting (,)/sort | |
time 402.1 ?s (391.6 ?s .. 412.1 ?s) | |
0.993 R? (0.990 R? .. 0.996 R?) | |
mean 394.6 ?s (387.6 ?s .. 405.2 ?s) | |
std dev 29.00 ?s (22.01 ?s .. 43.22 ?s) | |
variance introduced by outliers: 65% (severely inflated) | |
benchmarking sorting (,)/staged cmpSSC | |
time 358.6 ?s (348.9 ?s .. 371.5 ?s) | |
0.987 R? (0.982 R? .. 0.992 R?) | |
mean 380.8 ?s (365.6 ?s .. 404.4 ?s) | |
std dev 66.67 ?s (45.33 ?s .. 93.75 ?s) | |
variance introduced by outliers: 92% (severely inflated) | |
-} | |
-- almost `whnf (length . f)` except it also forces each element | |
nfElem f x = whnf (foldr seq () . f) x | |
cmpSP = comparing (\(P c _) -> c) <> | |
comparing (\(P _ i) -> i) | |
cmpSC = comparing fst <> comparing snd | |
cmpSSP = [ onM (\ (P c _) -> c), | |
onIM (\(P _ i) -> i) ] | |
cmpSSC = [ onM fst, onIM snd] | |
onIM f xs = map toList $ IM.elems $ IM.fromListWith (<>) | |
[ (f x, S.singleton x) | x <- xs ] | |
onM f xs = map toList $ M.elems $ M.fromListWith (<>) | |
[ (f x, S.singleton x) | x <- xs ] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment