@@ -20,8 +20,16 @@ import Test.Tasty.Bench (bench, bgroup, defaultMain, env, nf, whnf)
2020import qualified Data.ByteString as BS
2121import qualified "hashmap" Data.HashMap as IHM
2222import qualified Data.HashMap.Strict as HM
23+ import qualified "unordered-containers" Data.HashSet as HS
2324import qualified Data.IntMap as IM
25+ import Data.List (foldl' )
2426import qualified Data.Map as M
27+ import Data.Maybe (fromMaybe )
28+ import qualified Data.Set as S
29+ import qualified Data.Vector as V
30+ import GHC.Generics (Generic )
31+ import Prelude hiding (lookup )
32+
2533import qualified Util.ByteString as UBS
2634import qualified Util.Int as UI
2735import qualified Util.String as US
@@ -37,6 +45,8 @@ instance NFData B where
3745data Env = Env {
3846 n :: ! Int ,
3947
48+ csz :: ! Int , -- container size
49+
4050 elems :: ! [(String , Int )],
4151 keys :: ! [String ],
4252 elemsBS :: ! [(BS. ByteString , Int )],
@@ -49,6 +59,11 @@ data Env = Env {
4959 keysBS' :: ! [BS. ByteString ],
5060 keysI' :: ! [Int ],
5161
62+ listOfHMs :: ! [HM. HashMap Int Int ],
63+ vecOfHMs :: ! (V. Vector (HM. HashMap Int Int )),
64+ hsetOfHMs :: ! (HS. HashSet (HM. HashMap Int Int )),
65+ setOfHMs :: ! (S. Set (HM. HashMap Int Int )),
66+
5267 keysDup :: ! [String ],
5368 keysDupBS :: ! [BS. ByteString ],
5469 keysDupI :: ! [Int ],
@@ -79,6 +94,20 @@ setupEnv :: IO Env
7994setupEnv = do
8095 let n = 2 ^ (12 :: Int )
8196
97+ -- When building a container of hashmaps, 'cn' will be the size of each.
98+ cn = n `div` 16
99+ -- 'csz' is the size of the container of hashmaps.
100+ csz = 2 ^ (7 :: Int )
101+
102+ values = [1 .. csz* cn]
103+
104+ chop _ [] = []
105+ chop k l =
106+ let (taken, left) = splitAt k l
107+ in taken : chop k left
108+
109+ vals = chop cn values
110+
82111 elems = zip keys [1 .. n]
83112 keys = US. rnd 8 n
84113 elemsBS = zip keysBS [1 .. n]
@@ -91,6 +120,11 @@ setupEnv = do
91120 keysBS' = UBS. rnd' 8 n
92121 keysI' = UI. rnd' (n+ n) n
93122
123+ listOfHMs = zipWith (\ x y -> HM. fromList (zip x y)) (repeat keysI) vals
124+ vecOfHMs = V. fromList listOfHMs
125+ hsetOfHMs = HS. fromList listOfHMs
126+ setOfHMs = S. fromList listOfHMs
127+
94128 keysDup = US. rnd 2 n
95129 keysDupBS = UBS. rnd 2 n
96130 keysDupI = UI. rnd (n`div` 4 ) n
@@ -128,8 +162,8 @@ main = do
128162 [
129163#ifdef BENCH_containers_Map
130164 env setupEnv $ \ ~ (Env {.. }) ->
131- -- * Comparison to other data structures
132- -- ** Map
165+ -- Comparison to other data structures
166+ -- Map
133167 bgroup " Map"
134168 [ bgroup " lookup"
135169 [ bench " String" $ whnf (lookupM keys) m
@@ -231,7 +265,7 @@ main = do
231265
232266 env setupEnv $ \ ~ (Env {.. }) ->
233267 bgroup " HashMap"
234- [ -- * Basic interface
268+ [ -- Basic interface
235269 bgroup " lookup"
236270 [ bench " String" $ whnf (lookup keys) hm
237271 , bench " ByteString" $ whnf (lookup keysBS) hmbs
@@ -313,6 +347,51 @@ main = do
313347 , bench " Int" $ whnf (isSubmapOfNaive hmiSubset) hmi
314348 ]
315349
350+ , bgroup " containerized"
351+ [ bgroup " lookup"
352+ [ bench " List" $ nf (lookupC keysI) listOfHMs
353+ , bench " Vector" $ nf (lookupC keysI) vecOfHMs
354+ , bench " HashSet" $ nf (lookupHS keysI) hsetOfHMs
355+ , bench " Set" $ nf (lookupS keysI) setOfHMs
356+ ]
357+ , bgroup " insert"
358+ [ bench " List" $ nf (insertC elemsI) listOfHMs
359+ , bench " Vector" $ nf (insertC elemsI) vecOfHMs
360+ , bench " HashSet" $ nf (insertHS elemsI) hsetOfHMs
361+ , bench " Set" $ nf (insertS elemsI) setOfHMs
362+ ]
363+ , bgroup " delete"
364+ [ bench " List" $ nf (deleteC keysI) listOfHMs
365+ , bench " Vector" $ nf (deleteC keysI) vecOfHMs
366+ , bench " HashSet" $ nf (deleteHS keysI) hsetOfHMs
367+ , bench " Set" $ nf (deleteS keysI) setOfHMs
368+ ]
369+ , bgroup " union"
370+ [ bench " List" $ whnf unionC listOfHMs
371+ , bench " Vector" $ whnf unionC vecOfHMs
372+ , bench " HashSet" $ whnf unionC hsetOfHMs
373+ , bench " Set" $ whnf unionC setOfHMs
374+ ]
375+ , bgroup " map"
376+ [ bench " List" $ nf (mapC (\ v -> v + 1 )) listOfHMs
377+ , bench " Vector" $ nf (mapC (\ v -> v + 1 )) vecOfHMs
378+ , bench " HashSet" $ nf (mapHS (\ v -> v + 1 )) hsetOfHMs
379+ , bench " Set" $ nf (mapS (\ v -> v + 1 )) setOfHMs
380+ ]
381+ , bgroup " intersection"
382+ [ bench " List" $ whnf intersectionC listOfHMs
383+ , bench " Vector" $ whnf intersectionC vecOfHMs
384+ , bench " HashSet" $ whnf intersectionC hsetOfHMs
385+ , bench " Set" $ whnf intersectionC setOfHMs
386+ ]
387+ , bgroup " size"
388+ [ bench " List" $ nf sizeC listOfHMs
389+ , bench " Vector" $ nf sizeC vecOfHMs
390+ , bench " HashSet" $ nf sizeHS hsetOfHMs
391+ , bench " Set" $ nf sizeS setOfHMs
392+ ]
393+ ]
394+
316395 -- Combine
317396 , bgroup " union"
318397 [ bench " Int" $ whnf (HM. union hmi) hmi2
@@ -327,7 +406,7 @@ main = do
327406 -- Transformations
328407 , bench " map" $ whnf (HM. map (\ v -> v + 1 )) hmi
329408
330- -- * Difference and intersection
409+ -- Difference and intersection
331410 , bench " difference" $ whnf (HM. difference hmi) hmi2
332411
333412 -- Folds
@@ -389,6 +468,18 @@ lookup xs m = foldl' (\z k -> fromMaybe z (HM.lookup k m)) 0 xs
389468{-# SPECIALIZE lookup :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
390469 -> Int #-}
391470
471+ lookupC :: (Eq k , Hashable k , Traversable f ) => [k ] -> f (HM. HashMap k Int ) -> f Int
472+ lookupC = fmap . lookup
473+ {-# SPECIALIZE lookupC :: [Int] -> [HM.HashMap Int Int] -> [Int] #-}
474+ {-# SPECIALIZE lookupC :: [Int] -> V.Vector (HM.HashMap Int Int)
475+ -> V.Vector Int #-}
476+
477+ lookupHS :: [Int ] -> HS. HashSet (HM. HashMap Int Int ) -> HS. HashSet Int
478+ lookupHS = HS. map . lookup
479+
480+ lookupS :: [Int ] -> S. Set (HM. HashMap Int Int ) -> S. Set Int
481+ lookupS = S. map . lookup
482+
392483insert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
393484 -> HM. HashMap k Int
394485insert xs m0 = foldl' (\ m (k, v) -> HM. insert k v m) m0 xs
@@ -399,6 +490,21 @@ insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
399490{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
400491 -> HM.HashMap BS.ByteString Int #-}
401492
493+ insertC :: (Eq k , Hashable k , Traversable f ) => [(k , Int )] -> f (HM. HashMap k Int )
494+ -> f (HM. HashMap k Int )
495+ insertC l = fmap (insert l)
496+ {-# SPECIALIZE insertC :: [(Int, Int)] -> [HM.HashMap Int Int]
497+ -> [HM.HashMap Int Int] #-}
498+ {-# SPECIALIZE insertC :: [(Int, Int)] -> V.Vector (HM.HashMap Int Int)
499+ -> V.Vector (HM.HashMap Int Int) #-}
500+
501+ insertHS :: [(Int , Int )] -> HS. HashSet (HM. HashMap Int Int )
502+ -> HS. HashSet (HM. HashMap Int Int )
503+ insertHS l = HS. map (insert l)
504+
505+ insertS :: [(Int , Int )] -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
506+ insertS l = S. map (insert l)
507+
402508delete :: (Eq k , Hashable k ) => [k ] -> HM. HashMap k Int -> HM. HashMap k Int
403509delete xs m0 = foldl' (\ m k -> HM. delete k m) m0 xs
404510{-# SPECIALIZE delete :: [Int] -> HM.HashMap Int Int -> HM.HashMap Int Int #-}
@@ -407,6 +513,21 @@ delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
407513{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
408514 -> HM.HashMap BS.ByteString Int #-}
409515
516+ deleteC :: (Eq k , Hashable k , Functor f ) => [k ] -> f (HM. HashMap k Int )
517+ -> f (HM. HashMap k Int )
518+ deleteC = fmap . delete
519+ {-# SPECIALIZE deleteC :: [Int] -> [HM.HashMap Int Int]
520+ -> [HM.HashMap Int Int] #-}
521+ {-# SPECIALIZE deleteC :: [Int] -> V.Vector (HM.HashMap Int Int)
522+ -> V.Vector (HM.HashMap Int Int) #-}
523+
524+ deleteHS :: [Int ] -> HS. HashSet (HM. HashMap Int Int )
525+ -> HS. HashSet (HM. HashMap Int Int )
526+ deleteHS = HS. map . delete
527+
528+ deleteS :: [Int ] -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
529+ deleteS = S. map . delete
530+
410531alterInsert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
411532 -> HM. HashMap k Int
412533alterInsert xs m0 =
@@ -451,6 +572,52 @@ alterFDelete xs m0 =
451572{-# SPECIALIZE alterFDelete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
452573 -> HM.HashMap BS.ByteString Int #-}
453574
575+ unionC :: (Eq k , Hashable k , Foldable f ) => f (HM. HashMap k Int )
576+ -> HM. HashMap k Int
577+ unionC = foldl' HM. union mempty
578+ {-# SPECIALIZE unionC :: [HM.HashMap Int Int] -> HM.HashMap Int Int #-}
579+ {-# SPECIALIZE unionC :: V.Vector (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
580+ {-# SPECIALIZE unionC :: HS.HashSet (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
581+ {-# SPECIALIZE unionC :: S.Set (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
582+
583+ mapC :: (Eq k , Hashable k , Functor f ) => (Int -> Int ) -> f (HM. HashMap k Int )
584+ -> f (HM. HashMap k Int )
585+ mapC f = fmap (HM. map f)
586+ {-# SPECIALIZE mapC :: (Int -> Int) -> [HM.HashMap Int Int]
587+ -> [HM.HashMap Int Int] #-}
588+ {-# SPECIALIZE mapC :: (Int -> Int) -> V.Vector (HM.HashMap Int Int)
589+ -> V.Vector (HM.HashMap Int Int) #-}
590+
591+ mapHS :: (Int -> Int ) -> HS. HashSet (HM. HashMap Int Int )
592+ -> HS. HashSet (HM. HashMap Int Int )
593+ mapHS f = HS. map (HM. map f)
594+
595+ mapS :: (Int -> Int ) -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
596+ mapS f = S. map (HM. map f)
597+
598+ intersectionC :: (Eq k , Hashable k , Foldable f ) => f (HM. HashMap k Int )
599+ -> HM. HashMap k Int
600+ intersectionC = foldl' HM. intersection mempty
601+ {-# SPECIALIZE intersectionC :: [HM.HashMap Int Int]
602+ -> HM.HashMap Int Int #-}
603+ {-# SPECIALIZE intersectionC :: V.Vector (HM.HashMap Int Int)
604+ -> HM.HashMap Int Int #-}
605+ {-# SPECIALIZE intersectionC :: HS.HashSet (HM.HashMap Int Int)
606+ -> HM.HashMap Int Int #-}
607+ {-# SPECIALIZE intersectionC :: S.Set (HM.HashMap Int Int)
608+ -> HM.HashMap Int Int #-}
609+
610+ sizeC :: (Eq k , Hashable k , Functor f ) => f (HM. HashMap k Int ) -> f Int
611+ sizeC = fmap HM. size
612+ {-# SPECIALIZE sizeC :: [HM.HashMap Int Int] -> [Int] #-}
613+ {-# SPECIALIZE sizeC :: V.Vector (HM.HashMap Int Int) -> V.Vector Int #-}
614+
615+ sizeHS :: HS. HashSet (HM. HashMap Int Int ) -> HS. HashSet Int
616+ sizeHS = HS. map HM. size
617+
618+ sizeS :: S. Set (HM. HashMap Int Int ) -> S. Set Int
619+ sizeS = S. map HM. size
620+
454621isSubmapOfNaive :: (Eq k , Hashable k ) => HM. HashMap k Int -> HM. HashMap k Int -> Bool
455622isSubmapOfNaive m1 m2 = and [ Just v1 == HM. lookup k1 m2 | (k1,v1) <- HM. toList m1 ]
456623{-# SPECIALIZE isSubmapOfNaive :: HM.HashMap Int Int -> HM.HashMap Int Int -> Bool #-}
0 commit comments