Skip to content

Commit ae3c3b4

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

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

benchmarks/Benchmarks.hs

+127
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,39 @@ 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+
]
292+
231293
-- Combine
232294
, bench "union" $ whnf (HM.union hmi) hmi2
233295

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

357+
lookupC :: (Eq k, Hashable k, Traversable f) => [k] -> f (HM.HashMap k Int) -> f Int
358+
lookupC = fmap . lookup
359+
{-# SPECIALIZE lookupC :: [Int] -> [HM.HashMap Int Int] -> [Int] #-}
360+
{-# SPECIALIZE lookupC :: [Int] -> V.Vector (HM.HashMap Int Int)
361+
-> V.Vector Int #-}
362+
363+
lookupHS :: [Int] -> HS.HashSet (HM.HashMap Int Int) -> HS.HashSet Int
364+
lookupHS = HS.map . lookup
365+
366+
lookupS :: [Int] -> S.Set (HM.HashMap Int Int) -> S.Set Int
367+
lookupS = S.map . lookup
368+
295369
insert :: (Eq k, Hashable k) => [(k, Int)] -> HM.HashMap k Int
296370
-> HM.HashMap k Int
297371
insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
@@ -302,6 +376,21 @@ insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
302376
{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
303377
-> HM.HashMap BS.ByteString Int #-}
304378

379+
insertC :: (Eq k, Hashable k, Traversable f) => [(k, Int)] -> f (HM.HashMap k Int)
380+
-> f (HM.HashMap k Int)
381+
insertC l = fmap (insert l)
382+
{-# SPECIALIZE insertC :: [(Int, Int)] -> [HM.HashMap Int Int]
383+
-> [HM.HashMap Int Int] #-}
384+
{-# SPECIALIZE insertC :: [(Int, Int)] -> V.Vector (HM.HashMap Int Int)
385+
-> V.Vector (HM.HashMap Int Int) #-}
386+
387+
insertHS :: [(Int, Int)] -> HS.HashSet (HM.HashMap Int Int)
388+
-> HS.HashSet (HM.HashMap Int Int)
389+
insertHS l = HS.map (insert l)
390+
391+
insertS :: [(Int, Int)] -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
392+
insertS l = S.map (insert l)
393+
305394
delete :: (Eq k, Hashable k) => [k] -> HM.HashMap k Int -> HM.HashMap k Int
306395
delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
307396
{-# SPECIALIZE delete :: [Int] -> HM.HashMap Int Int -> HM.HashMap Int Int #-}
@@ -310,6 +399,44 @@ delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
310399
{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
311400
-> HM.HashMap BS.ByteString Int #-}
312401

402+
deleteC :: (Eq k, Hashable k, Functor f) => [k] -> f (HM.HashMap k Int)
403+
-> f (HM.HashMap k Int)
404+
deleteC = fmap . delete
405+
{-# SPECIALIZE deleteC :: [Int] -> [HM.HashMap Int Int]
406+
-> [HM.HashMap Int Int] #-}
407+
{-# SPECIALIZE deleteC :: [Int] -> V.Vector (HM.HashMap Int Int)
408+
-> V.Vector (HM.HashMap Int Int) #-}
409+
410+
deleteHS :: [Int] -> HS.HashSet (HM.HashMap Int Int)
411+
-> HS.HashSet (HM.HashMap Int Int)
412+
deleteHS = HS.map . delete
413+
414+
deleteS :: [Int] -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
415+
deleteS = S.map . delete
416+
417+
unionC :: (Eq k, Hashable k, Foldable f) => f (HM.HashMap k Int)
418+
-> HM.HashMap k Int
419+
unionC = foldl' HM.union mempty
420+
{-# SPECIALIZE unionC :: [HM.HashMap Int Int] -> HM.HashMap Int Int #-}
421+
{-# SPECIALIZE unionC :: V.Vector (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
422+
{-# SPECIALIZE unionC :: HS.HashSet (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
423+
{-# SPECIALIZE unionC :: S.Set (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
424+
425+
mapC :: (Eq k, Hashable k, Functor f) => (Int -> Int) -> f (HM.HashMap k Int)
426+
-> f (HM.HashMap k Int)
427+
mapC f = fmap (HM.map f)
428+
{-# SPECIALIZE mapC :: (Int -> Int) -> [HM.HashMap Int Int]
429+
-> [HM.HashMap Int Int] #-}
430+
{-# SPECIALIZE mapC :: (Int -> Int) -> V.Vector (HM.HashMap Int Int)
431+
-> V.Vector (HM.HashMap Int Int) #-}
432+
433+
mapHS :: (Int -> Int) -> HS.HashSet (HM.HashMap Int Int)
434+
-> HS.HashSet (HM.HashMap Int Int)
435+
mapHS f = HS.map (HM.map f)
436+
437+
mapS :: (Int -> Int) -> S.Set (HM.HashMap Int Int) -> S.Set (HM.HashMap Int Int)
438+
mapS f = S.map (HM.map f)
439+
313440
------------------------------------------------------------------------
314441
-- * Map
315442

benchmarks/unordered-containers-benchmarks.cabal

+1
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

+1
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)