cuckoo-filter-0.2.0.1: benchmarks/Benchmarks/Simple.hs
module Benchmarks.Simple (
stdInBenchmark,
stdInMutableBenchmark,
tenPctPacked,
fiftyPctPacked,
ninetyPctPacked
) where
import Criterion
import Control.Monad (foldM)
import Data.CuckooFilter
import Data.Functor.Identity (runIdentity)
import Data.Ratio (Ratio)
import Numeric.Natural (Natural)
import System.Environment
import System.Random
stdInBenchmark :: IO ()
stdInBenchmark = do
[n, m] <- fmap read <$> getArgs
let (Just s) = makeSize (fromIntegral n)
filt = runIdentity $ initialize s :: Filter Int
print s
filt' <- pure $ foldM (\ f a -> f `insertIdent` a) filt [1..m]
print $ (runIdentity . member 1) <$> filt'
stdInMutableBenchmark :: IO ()
stdInMutableBenchmark = do
[n, m] <- fmap read <$> getArgs
let (Just s) = makeSize (fromIntegral n)
filt <- initialize s :: IO (MFilter Int)
print s
filt' <- foldMaybeM (\f a -> f `insert` a) filt [1..m]
case filt' of
Nothing -> print "Collision occurred. Exiting."
Just res -> print =<< member 1 res
where
foldMaybeM :: (Monad m) => (b -> a -> m (Maybe b)) -> b -> [a] -> m (Maybe b)
foldMaybeM f seed [] = pure (Just seed)
foldMaybeM f seed (x:xs) = do
res <- f seed x
case res of
Just seed' -> foldMaybeM f seed' xs
Nothing -> pure Nothing
tenPctPacked :: Benchmark
tenPctPacked = bgroup "10% packed" [
bench "Store 100k, 1% dupes" $ whnf (doTest oneMM (LF 10)) (D 1),
bench "Store 100k, 10% dupes" $ whnf (doTest oneMM (LF 10)) (D 10),
bench "Store 100k, 50% dupes" $ whnf (doTest oneMM (LF 10)) (D 50),
bench "Store 10MM, 1% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 1),
bench "Store 10MM, 10% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 10),
bench "Store 10MM, 50% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 50)
]
fiftyPctPacked :: Benchmark
fiftyPctPacked = bgroup "50% packed" [
bench "Store 500k, 1% dupes" $ whnf (doTest oneMM (LF 50)) (D 1),
bench "Store 500k, 10% dupes" $ whnf (doTest oneMM (LF 50)) (D 10),
bench "Store 500k, 50% dupes" $ whnf (doTest oneMM (LF 50)) (D 50),
bench "Store 50MM, 1% dupes" $ whnf (doTest oneHundredMM (LF 50)) (D 1),
bench "Store 50MM, 10% dupes" $ whnf (doTest oneHundredMM (LF 50)) (D 10),
bench "Store 50MM, 50% dupes" $ whnf (doTest oneHundredMM (LF 50)) (D 50)
]
ninetyPctPacked :: Benchmark
ninetyPctPacked = bgroup "90% packed" [
bench "Store 900k, 1% dupes" $ whnf (doTest oneMM (LF 90)) (D 1),
bench "Store 900k, 10% dupes" $ whnf (doTest oneMM (LF 90)) (D 10),
bench "Store 900k, 50% dupes" $ whnf (doTest oneMM (LF 90)) (D 50),
bench "Store 90MM, 1% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 1),
bench "Store 90MM, 10% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 10),
bench "Store 90MM, 50% dupes" $ whnf (doTest oneHundredMM (LF 10)) (D 50)
]
oneMM :: Natural
oneMM = 1000000
oneHundredMM :: Natural
oneHundredMM = oneMM * 100
newtype DupePct = D Natural
newtype LoadFactor = LF Natural
doTest ::
Natural
-> LoadFactor
-> DupePct
-> Maybe (Filter Int)
doTest size (LF lf) (D d) = do
filt <- initialize s
foldM insertIdent filt vals
where
valCount :: Int
valCount = floor $ (fromIntegral size) * (realToFrac lf / 100.0)
dupeCount :: Int
dupeCount = floor $ (fromIntegral valCount) * (realToFrac d / 100.0)
dupes = if d > 0
then [1.. dupeCount]
else []
vals = dupes <> [1..(valCount - dupeCount)]
Just s = makeSize size
insertIdent ::
Filter Int
-> Int
-> Maybe (Filter Int)
insertIdent filt n = runIdentity $ insert filt n