bitvec-1.1.2.0: bench/Bench/RandomWrite.hs
module Bench.RandomWrite
( benchRandomWrite
) where
import Control.Monad
import Control.Monad.ST
import Data.Bit
import qualified Data.Bit.ThreadSafe as TS
import Data.Bits
import Data.Foldable
import qualified Data.IntSet as IS
import qualified Data.Vector.Unboxed.Mutable as MU
import System.Random
import Test.Tasty.Bench
randomWrites :: [(Int, Bool)]
randomWrites
= map (\x -> if x > 0 then (x, True) else (negate x, False))
. randoms
. mkStdGen
$ 42
benchRandomWrite :: Int -> Benchmark
benchRandomWrite k = bgroup (show (1 `shiftL` k :: Int))
[ bench "Bit" $ nf randomWriteBit k
, bench "Bit.TS" $ nf randomWriteBitTS k
, bench "Vector" $ nf randomWriteVector k
, bench "IntSet" $ nf randomWriteIntSet k
]
randomWriteBit :: Int -> Int
randomWriteBit k = runST $ do
let n = 1 `shiftL` k
vec <- MU.new n
forM_ (take (mult * n) randomWrites) $
\(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) (Bit b)
Bit i <- MU.unsafeRead vec 0
pure $ if i then 1 else 0
randomWriteBitTS :: Int -> Int
randomWriteBitTS k = runST $ do
let n = 1 `shiftL` k
vec <- MU.new n
forM_ (take (mult * n) randomWrites) $
\(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) (TS.Bit b)
TS.Bit i <- MU.unsafeRead vec 0
pure $ if i then 1 else 0
randomWriteVector :: Int -> Int
randomWriteVector k = runST $ do
let n = 1 `shiftL` k
vec <- MU.new n
forM_ (take (mult * n) randomWrites) $
\(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) b
i <- MU.unsafeRead vec 0
pure $ if i then 1 else 0
randomWriteIntSet :: Int -> Int
randomWriteIntSet k = if IS.member 0 vec then 1 else 0
where
n = 1 `shiftL` k
vec = foldl'
(\acc (i, b) -> (if b then IS.insert else IS.delete) (i .&. (1 `shiftL` k - 1)) acc)
mempty
(take (mult * n) randomWrites)
mult :: Int
mult = 100