Skip to content

Commit 97e9445

Browse files
committed
Add benchmarks to operations in containers of hashmaps
1 parent 147b05f commit 97e9445

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

benchmarks/Benchmarks.hs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import Data.Hashable (Hashable)
1010
import qualified Data.ByteString as BS
1111
import qualified "hashmap" Data.HashMap as IHM
1212
import qualified Data.HashMap.Strict as HM
13+
import qualified Data.HashSet as HS
1314
import qualified Data.IntMap as IM
1415
import qualified Data.Map as M
16+
import qualified Data.Set as S
17+
import qualified Data.Vector as V
1518
import Data.List (foldl')
1619
import Data.Maybe (fromMaybe)
1720
import GHC.Generics (Generic)
@@ -36,6 +39,8 @@ instance NFData B where
3639
data Env = Env {
3740
n :: !Int,
3841

42+
csz :: !Int, -- container size
43+
3944
elems :: ![(String, Int)],
4045
keys :: ![String],
4146
elemsBS :: ![(BS.ByteString, Int)],
@@ -48,6 +53,11 @@ data Env = Env {
4853
keysBS' :: ![BS.ByteString],
4954
keysI' :: ![Int],
5055

56+
listOfHMs :: ![HM.HashMap Int Int],
57+
vecOfHMs :: !(V.Vector (HM.HashMap Int Int)),
58+
hsetOfHMs :: !(HS.HashSet (HM.HashMap Int Int)),
59+
setOfHMs :: !(S.Set (HM.HashMap Int Int)),
60+
5161
keysDup :: ![String],
5262
keysDupBS :: ![BS.ByteString],
5363
keysDupI :: ![Int],
@@ -72,6 +82,20 @@ setupEnv :: IO Env
7282
setupEnv = do
7383
let n = 2^(12 :: Int)
7484

85+
-- When building a container of hashmaps, 'cn' will be the size of each.
86+
cn = n `div` 16
87+
-- 'csz' is the size of the container of hashmaps.
88+
csz = 2^(7 :: Int)
89+
90+
values = [1..csz*cn]
91+
92+
chop _ [] = []
93+
chop k l =
94+
let (taken, left) = splitAt k l
95+
in taken : chop k left
96+
97+
vals = chop cn values
98+
7599
elems = zip keys [1..n]
76100
keys = US.rnd 8 n
77101
elemsBS = zip keysBS [1..n]
@@ -84,6 +108,11 @@ setupEnv = do
84108
keysBS' = UBS.rnd' 8 n
85109
keysI' = UI.rnd' (n+n) n
86110

111+
listOfHMs = zipWith (\x y -> HM.fromList (zip x y)) (repeat keysI) vals
112+
vecOfHMs = V.fromList listOfHMs
113+
hsetOfHMs = HS.fromList listOfHMs
114+
setOfHMs = S.fromList listOfHMs
115+
87116
keysDup = US.rnd 2 n
88117
keysDupBS = UBS.rnd 2 n
89118
keysDupI = UI.rnd (n`div`4) n
@@ -228,6 +257,57 @@ main = do
228257
, bench "Int" $ whnf (delete keysI') hmi
229258
]
230259

260+
, bgroup "containerized"
261+
[ bgroup "lookup"
262+
[ bench "List" $ nf (lookupC keysI) listOfHMs
263+
, bench "Vector" $ nf (lookupC keysI) vecOfHMs
264+
, bench "HashSet" $ nf (lookupHS keysI) hsetOfHMs
265+
, bench "Set" $ nf (lookupS keysI) setOfHMs
266+
]
267+
, bgroup "insert"
268+
[ bench "List" $ nf (insertC elemsI) listOfHMs
269+
, bench "Vector" $ nf (insertC elemsI) vecOfHMs
270+
, bench "HashSet" $ nf (insertHS elemsI) hsetOfHMs
271+
, bench "Set" $ nf (insertS elemsI) setOfHMs
272+
]
273+
, bgroup "delete"
274+
[ bench "List" $ nf (deleteC keysI) listOfHMs
275+
, bench "Vector" $ nf (deleteC keysI) vecOfHMs
276+
, bench "HashSet" $ nf (deleteHS keysI) hsetOfHMs
277+
, bench "Set" $ nf (deleteS keysI) setOfHMs
278+
]
279+
, bgroup "union"
280+
[ bench "List" $ whnf unionC listOfHMs
281+
, bench "Vector" $ whnf unionC vecOfHMs
282+
, bench "HashSet" $ whnf unionC hsetOfHMs
283+
, bench "Set" $ whnf unionC setOfHMs
284+
]
285+
, bgroup "containerized map"
286+
[ bench "List" $ nf (mapC (\ v -> v + 1)) listOfHMs
287+
, bench "Vector" $ nf (mapC (\ v -> v + 1)) vecOfHMs
288+
, bench "HashSet" $ nf (mapHS (\ v -> v + 1)) hsetOfHMs
289+
, bench "Set" $ nf (mapS (\ v -> v + 1)) setOfHMs
290+
]
291+
, bgroup "union"
292+
[ bench "List" $ whnf unionC listOfHMs
293+
, bench "Vector" $ whnf unionC vecOfHMs
294+
, bench "HashSet" $ whnf unionC hsetOfHMs
295+
, bench "Set" $ whnf unionC setOfHMs
296+
]
297+
, bgroup "intersection"
298+
[ bench "List" $ whnf intersectionC listOfHMs
299+
, bench "Vector" $ whnf intersectionC vecOfHMs
300+
, bench "HashSet" $ whnf intersectionC hsetOfHMs
301+
, bench "Set" $ whnf intersectionC setOfHMs
302+
]
303+
, bgroup "size"
304+
[ bench "List" $ nf sizeC listOfHMs
305+
, bench "Vector" $ nf sizeC vecOfHMs
306+
, bench "HashSet" $ nf sizeHS hsetOfHMs
307+
, bench "Set" $ nf sizeS setOfHMs
308+
]
309+
]
310+
231311
-- Combine
232312
, bench "union" $ whnf (HM.union hmi) hmi2
233313

@@ -292,6 +372,18 @@ lookup xs m = foldl' (\z k -> fromMaybe z (HM.lookup k m)) 0 xs
292372
{-# SPECIALIZE lookup :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
293373
-> Int #-}
294374

375+
lookupC :: (Eq k, Hashable k, Traversable f) => [k] -> f (HM.HashMap k Int) -> f Int
376+
lookupC = fmap . lookup
377+
{-# SPECIALIZE lookupC :: [Int] -> [HM.HashMap Int Int] -> [Int] #-}
378+
{-# SPECIALIZE lookupC :: [Int] -> V.Vector (HM.HashMap Int Int)
379+
-> V.Vector Int #-}
380+
381+
lookupHS :: [Int] -> HS.HashSet (HM.HashMap Int Int) -> HS.HashSet Int
382+
lookupHS = HS.map . lookup
383+
384+
lookupS :: [Int] -> S.Set (HM.HashMap Int Int) -> S.Set Int
385+
lookupS = S.map . lookup
386+
295387
insert :: (Eq k, Hashable k) => [(k, Int)] -> HM.HashMap k Int
296388
-> HM.HashMap k Int
297389
insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
@@ -302,6 +394,21 @@ insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
302394
{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
303395
-> HM.HashMap BS.ByteString Int #-}
304396

397+
insertC :: (Eq k, Hashable k, Traversable f) => [(k, Int)] -> f (HM.HashMap k Int)
398+
-> f (HM.HashMap k Int)
399+
insertC l = fmap (insert l)
400+
{-# SPECIALIZE insertC :: [(Int, Int)] -> [HM.HashMap Int Int]
401+
-> [HM.HashMap Int Int] #-}
402+
{-# SPECIALIZE insertC :: [(Int, Int)] -> V.Vector (HM.HashMap Int Int)
403+
-> V.Vector (HM.HashMap Int Int) #-}
404+
405+
insertHS :: [(Int, Int)] -> HS.HashSet (HM.HashMap Int Int)
406+
-> HS.HashSet (HM.HashMap Int Int)
407+
insertHS l = HS.map (insert l)
408+
409+
insertS :: [(Int, Int)] -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
410+
insertS l = S.map (insert l)
411+
305412
delete :: (Eq k, Hashable k) => [k] -> HM.HashMap k Int -> HM.HashMap k Int
306413
delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
307414
{-# SPECIALIZE delete :: [Int] -> HM.HashMap Int Int -> HM.HashMap Int Int #-}
@@ -310,6 +417,66 @@ delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
310417
{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
311418
-> HM.HashMap BS.ByteString Int #-}
312419

420+
deleteC :: (Eq k, Hashable k, Functor f) => [k] -> f (HM.HashMap k Int)
421+
-> f (HM.HashMap k Int)
422+
deleteC = fmap . delete
423+
{-# SPECIALIZE deleteC :: [Int] -> [HM.HashMap Int Int]
424+
-> [HM.HashMap Int Int] #-}
425+
{-# SPECIALIZE deleteC :: [Int] -> V.Vector (HM.HashMap Int Int)
426+
-> V.Vector (HM.HashMap Int Int) #-}
427+
428+
deleteHS :: [Int] -> HS.HashSet (HM.HashMap Int Int)
429+
-> HS.HashSet (HM.HashMap Int Int)
430+
deleteHS = HS.map . delete
431+
432+
deleteS :: [Int] -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
433+
deleteS = S.map . delete
434+
435+
unionC :: (Eq k, Hashable k, Foldable f) => f (HM.HashMap k Int)
436+
-> HM.HashMap k Int
437+
unionC = foldl' HM.union mempty
438+
{-# SPECIALIZE unionC :: [HM.HashMap Int Int] -> HM.HashMap Int Int #-}
439+
{-# SPECIALIZE unionC :: V.Vector (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
440+
{-# SPECIALIZE unionC :: HS.HashSet (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
441+
{-# SPECIALIZE unionC :: S.Set (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
442+
443+
mapC :: (Eq k, Hashable k, Functor f) => (Int -> Int) -> f (HM.HashMap k Int)
444+
-> f (HM.HashMap k Int)
445+
mapC f = fmap (HM.map f)
446+
{-# SPECIALIZE mapC :: (Int -> Int) -> [HM.HashMap Int Int]
447+
-> [HM.HashMap Int Int] #-}
448+
{-# SPECIALIZE mapC :: (Int -> Int) -> V.Vector (HM.HashMap Int Int)
449+
-> V.Vector (HM.HashMap Int Int) #-}
450+
451+
mapHS :: (Int -> Int) -> HS.HashSet (HM.HashMap Int Int)
452+
-> HS.HashSet (HM.HashMap Int Int)
453+
mapHS f = HS.map (HM.map f)
454+
455+
mapS :: (Int -> Int) -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
456+
mapS f = S.map (HM.map f)
457+
458+
intersectionC :: (Eq k, Hashable k, Foldable f) => f (HM.HashMap k Int)
459+
-> HM.HashMap k Int
460+
intersectionC = foldl' HM.intersection mempty
461+
{-# SPECIALIZE intersectionC :: [HM.HashMap Int Int]
462+
-> HM.HashMap Int Int #-}
463+
{-# SPECIALIZE intersectionC :: V.Vector (HM.HashMap Int Int)
464+
-> HM.HashMap Int Int #-}
465+
{-# SPECIALIZE intersectionC :: HS.HashSet (HM.HashMap Int Int)
466+
-> HM.HashMap Int Int #-}
467+
{-# SPECIALIZE intersectionC :: S.Set (HM.HashMap Int Int)
468+
-> HM.HashMap Int Int #-}
469+
470+
sizeC :: (Eq k, Hashable k, Functor f) => f (HM.HashMap k Int) -> f Int
471+
sizeC = fmap HM.size
472+
{-# SPECIALIZE sizeC :: [HM.HashMap Int Int] -> [Int] #-}
473+
{-# SPECIALIZE sizeC :: V.Vector (HM.HashMap Int Int) -> V.Vector Int #-}
474+
475+
sizeHS :: HS.HashSet (HM.HashMap Int Int) -> HS.HashSet Int
476+
sizeHS = HS.map HM.size
477+
478+
sizeS :: S.Set (HM.HashMap Int Int) -> S.Set Int
479+
sizeS = S.map HM.size
313480
------------------------------------------------------------------------
314481
-- * Map
315482

benchmarks/unordered-containers-benchmarks.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ executable unordered-containers-benchmarks
2424
base,
2525
bytestring,
2626
containers,
27+
vector,
2728
criterion,
2829
deepseq,
2930
deepseq-generics,

unordered-containers.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ benchmark benchmarks
179179
base,
180180
bytestring,
181181
containers,
182+
vector,
182183
criterion >= 1.0 && < 1.3,
183184
deepseq >= 1.1,
184185
deepseq-generics,

0 commit comments

Comments
 (0)