{-# LANGUAGE OverloadedStrings #-}
module Main where
import Criterion.Main
import Data.Word
import HaskellWorks.Data.BalancedParens.FindClose
import HaskellWorks.Data.Bits.BitShow
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Bits.Broadword.Type
import HaskellWorks.Data.Bits.FromBitTextByteString
import HaskellWorks.Data.Naive
import HaskellWorks.Data.Ops
import qualified Data.Vector.Storable as DVS
import qualified HaskellWorks.Data.BalancedParens.Broadword.Word64 as BW64
import qualified HaskellWorks.Data.BalancedParens.Gen as G
import qualified HaskellWorks.Data.BalancedParens.Internal.Slow.Word64 as SW64
import qualified HaskellWorks.Data.BalancedParens.ParensSeq as PS
import qualified HaskellWorks.Data.BalancedParens.RangeMin as RM
import qualified HaskellWorks.Data.BalancedParens.RangeMin2 as RM2
import qualified Hedgehog.Gen as G
import qualified Hedgehog.Range as R
setupEnvVector :: Int -> IO (DVS.Vector Word64)
setupEnvVector n = return $ DVS.fromList (take n (cycle [maxBound, 0]))
setupEnvRmVector :: Int -> IO (RM.RangeMin (DVS.Vector Word64))
setupEnvRmVector n = return $ RM.mkRangeMin $ DVS.fromList (take n (cycle [maxBound, 0]))
setupEnvRm2Vector :: Int -> IO (RM2.RangeMin2 (DVS.Vector Word64))
setupEnvRm2Vector n = return $ RM2.mkRangeMin2 $ DVS.fromList (take n (cycle [maxBound, 0]))
setupEnvBP2 :: IO Word64
setupEnvBP2 = return $ DVS.head (fromBitTextByteString "10")
setupEnvBP4 :: IO Word64
setupEnvBP4 = return $ DVS.head (fromBitTextByteString "1100")
setupEnvBP8 :: IO Word64
setupEnvBP8 = return $ DVS.head (fromBitTextByteString "11101000")
setupEnvBP16 :: IO Word64
setupEnvBP16 = return $ DVS.head (fromBitTextByteString "11111000 11100000")
setupEnvBP32 :: IO Word64
setupEnvBP32 = return $ DVS.head (fromBitTextByteString "11111000 11101000 11101000 11100000")
setupEnvBP64 :: IO Word64
setupEnvBP64 = return $ DVS.head (fromBitTextByteString "11111000 11101000 11101000 11101000 11101000 11101000 11101000 11100000")
benchWord64 :: [Benchmark]
benchWord64 = foldMap mkBenchWord64Group [0 .. 64]
where mkBenchWord64Group :: Word64 -> [Benchmark]
mkBenchWord64Group p = let q = (1 .<. p) - 1 in
[ bgroup "Word64"
[ bench ("Broadword find close " <> bitShow q) (whnf (BW64.findCloseFar 0) q)
, bench ("Naive find close " <> bitShow q) (whnf (SW64.findCloseFar 0) q)
]
]
benchVector :: [Benchmark]
benchVector =
[ bgroup "Vector"
[ env setupEnvBP2 $ \w -> bgroup "FindClose 2-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env setupEnvBP4 $ \w -> bgroup "FindClose 4-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env setupEnvBP8 $ \w -> bgroup "FindClose 8-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env setupEnvBP16 $ \w -> bgroup "FindClose 16-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env setupEnvBP32 $ \w -> bgroup "FindClose 32-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env setupEnvBP64 $ \w -> bgroup "FindClose 64-bit"
[ bench "Broadword" (whnf (findClose (Broadword w)) 1)
, bench "Naive" (whnf (findClose (Naive w)) 1)
]
, env (setupEnvVector 1000000) $ \bv -> bgroup "Vanilla"
[ bench "findClose" (nf (map (findClose bv)) [0, 1000..10000000])
]
]
]
benchRm :: [Benchmark]
benchRm =
[ bgroup "Rm"
[ env (G.sample (G.storableVector (R.singleton 1000) (G.word64 R.constantBounded))) $ \v -> bgroup "Vector64"
[ bench "mkRangeMin" (nf RM.mkRangeMin v)
]
, env (setupEnvRmVector 1000000) $ \bv -> bgroup "RangeMin"
[ bench "findClose" (nf (map (findClose bv)) [0, 1000..10000000])
]
]
]
benchRm2 :: [Benchmark]
benchRm2 =
[ bgroup "Rm2"
[ env (G.sample (G.storableVector (R.singleton 1000) (G.word64 R.constantBounded))) $ \v -> bgroup "Vector64"
[ bench "mkRangeMin2" (nf RM2.mkRangeMin2 v)
]
, env (setupEnvRm2Vector 1000000) $ \bv -> bgroup "RangeMin2"
[ bench "findClose" (nf (map (findClose bv)) [0, 1000..10000000])
]
]
]
benchParensSeq :: [Benchmark]
benchParensSeq =
[ bgroup "ParensSeq"
[ env (G.sample (G.bpParensSeq (R.singleton 100000))) $ \ps -> bgroup "ParensSeq"
[ bench "firstChild" (nf (map (PS.firstChild ps)) [1,101..100000])
, bench "nextSibling" (nf (map (PS.nextSibling ps)) [1,101..100000])
, bench "(<|)" (nf (<| ps) True)
, bench "(|>)" (nf (ps |>) True)
, bench "drop" (nf (fmap (flip PS.drop ps)) [1,101..100000])
]
, env (G.sample (G.vec2 (G.bpParensSeq (R.singleton 100000)))) $ \ ~(ps1, ps2) -> bgroup "ParensSeq"
[ bench "(<>)" (nf (ps1 <>) ps2)
]
, env (G.sample (G.list (R.singleton 100) (G.word64 (R.constantBounded)))) $ \ws -> bgroup "ParensSeq"
[ bench "fromWord64s" (nf PS.fromWord64s ws)
]
]
]
main :: IO ()
main = defaultMain $ mempty
<> benchWord64
<> benchVector
<> benchRm
<> benchRm2
<> benchParensSeq