@@ -10,8 +10,11 @@ import Data.Hashable (Hashable, hash)
1010import qualified Data.ByteString as BS
1111import qualified "hashmap" Data.HashMap as IHM
1212import qualified Data.HashMap.Strict as HM
13+ import qualified "unordered-containers" Data.HashSet as HS
1314import qualified Data.IntMap as IM
1415import qualified Data.Map as M
16+ import qualified Data.Set as S
17+ import qualified Data.Vector as V
1518import Data.List (foldl' )
1619import Data.Maybe (fromMaybe )
1720import GHC.Generics (Generic )
@@ -36,6 +39,8 @@ instance NFData B where
3639data 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 ],
@@ -78,6 +88,20 @@ setupEnv :: IO Env
7888setupEnv = do
7989 let n = 2 ^ (12 :: Int )
8090
91+ -- When building a container of hashmaps, 'cn' will be the size of each.
92+ cn = n `div` 16
93+ -- 'csz' is the size of the container of hashmaps.
94+ csz = 2 ^ (7 :: Int )
95+
96+ values = [1 .. csz* cn]
97+
98+ chop _ [] = []
99+ chop k l =
100+ let (taken, left) = splitAt k l
101+ in taken : chop k left
102+
103+ vals = chop cn values
104+
81105 elems = zip keys [1 .. n]
82106 keys = US. rnd 8 n
83107 elemsBS = zip keysBS [1 .. n]
@@ -90,6 +114,11 @@ setupEnv = do
90114 keysBS' = UBS. rnd' 8 n
91115 keysI' = UI. rnd' (n+ n) n
92116
117+ listOfHMs = zipWith (\ x y -> HM. fromList (zip x y)) (repeat keysI) vals
118+ vecOfHMs = V. fromList listOfHMs
119+ hsetOfHMs = HS. fromList listOfHMs
120+ setOfHMs = S. fromList listOfHMs
121+
93122 keysDup = US. rnd 2 n
94123 keysDupBS = UBS. rnd 2 n
95124 keysDupI = UI. rnd (n`div` 4 ) n
@@ -126,8 +155,8 @@ main = do
126155 defaultMain
127156 [
128157 env setupEnv $ \ ~ (Env {.. }) ->
129- -- * Comparison to other data structures
130- -- ** Map
158+ -- Comparison to other data structures
159+ -- Map
131160 bgroup " Map"
132161 [ bgroup " lookup"
133162 [ bench " String" $ whnf (lookupM keys) m
@@ -167,7 +196,7 @@ main = do
167196 ]
168197 ]
169198
170- -- ** Map from the hashmap package
199+ -- Map from the hashmap package
171200 , env setupEnv $ \ ~ (Env {.. }) ->
172201 bgroup " hashmap/Map"
173202 [ bgroup " lookup"
@@ -212,7 +241,7 @@ main = do
212241 ]
213242 ]
214243
215- -- ** IntMap
244+ -- IntMap
216245 , env setupEnv $ \ ~ (Env {.. }) ->
217246 bgroup " IntMap"
218247 [ bench " lookup" $ whnf (lookupIM keysI) im
@@ -228,7 +257,7 @@ main = do
228257
229258 , env setupEnv $ \ ~ (Env {.. }) ->
230259 bgroup " HashMap"
231- [ -- * Basic interface
260+ [ -- Basic interface
232261 bgroup " lookup"
233262 [ bench " String" $ whnf (lookup keys) hm
234263 , bench " ByteString" $ whnf (lookup keysBS) hmbs
@@ -310,13 +339,103 @@ main = do
310339 , bench " Int" $ whnf (isSubmapOfNaive hmiSubset) hmi
311340 ]
312341
342+ , bgroup " containerized"
343+ [ bgroup " lookup"
344+ [ bench " List" $ nf (lookupC keysI) listOfHMs
345+ , bench " Vector" $ nf (lookupC keysI) vecOfHMs
346+ , bench " HashSet" $ nf (lookupHS keysI) hsetOfHMs
347+ , bench " Set" $ nf (lookupS keysI) setOfHMs
348+ ]
349+ , bgroup " insert"
350+ [ bench " List" $ nf (insertC elemsI) listOfHMs
351+ , bench " Vector" $ nf (insertC elemsI) vecOfHMs
352+ , bench " HashSet" $ nf (insertHS elemsI) hsetOfHMs
353+ , bench " Set" $ nf (insertS elemsI) setOfHMs
354+ ]
355+ , bgroup " delete"
356+ [ bench " List" $ nf (deleteC keysI) listOfHMs
357+ , bench " Vector" $ nf (deleteC keysI) vecOfHMs
358+ , bench " HashSet" $ nf (deleteHS keysI) hsetOfHMs
359+ , bench " Set" $ nf (deleteS keysI) setOfHMs
360+ ]
361+ , bgroup " union"
362+ [ bench " List" $ whnf unionC listOfHMs
363+ , bench " Vector" $ whnf unionC vecOfHMs
364+ , bench " HashSet" $ whnf unionC hsetOfHMs
365+ , bench " Set" $ whnf unionC setOfHMs
366+ ]
367+ , bgroup " map"
368+ [ bench " List" $ nf (mapC (\ v -> v + 1 )) listOfHMs
369+ , bench " Vector" $ nf (mapC (\ v -> v + 1 )) vecOfHMs
370+ , bench " HashSet" $ nf (mapHS (\ v -> v + 1 )) hsetOfHMs
371+ , bench " Set" $ nf (mapS (\ v -> v + 1 )) setOfHMs
372+ ]
373+ , bgroup " intersection"
374+ [ bench " List" $ whnf intersectionC listOfHMs
375+ , bench " Vector" $ whnf intersectionC vecOfHMs
376+ , bench " HashSet" $ whnf intersectionC hsetOfHMs
377+ , bench " Set" $ whnf intersectionC setOfHMs
378+ ]
379+ , bgroup " size"
380+ [ bench " List" $ nf sizeC listOfHMs
381+ , bench " Vector" $ nf sizeC vecOfHMs
382+ , bench " HashSet" $ nf sizeHS hsetOfHMs
383+ , bench " Set" $ nf sizeS setOfHMs
384+ ]
385+ ]
386+
387+ , bgroup " containerized"
388+ [ bgroup " lookup"
389+ [ bench " List" $ nf (lookupC keysI) listOfHMs
390+ , bench " Vector" $ nf (lookupC keysI) vecOfHMs
391+ , bench " HashSet" $ nf (lookupHS keysI) hsetOfHMs
392+ , bench " Set" $ nf (lookupS keysI) setOfHMs
393+ ]
394+ , bgroup " insert"
395+ [ bench " List" $ nf (insertC elemsI) listOfHMs
396+ , bench " Vector" $ nf (insertC elemsI) vecOfHMs
397+ , bench " HashSet" $ nf (insertHS elemsI) hsetOfHMs
398+ , bench " Set" $ nf (insertS elemsI) setOfHMs
399+ ]
400+ , bgroup " delete"
401+ [ bench " List" $ nf (deleteC keysI) listOfHMs
402+ , bench " Vector" $ nf (deleteC keysI) vecOfHMs
403+ , bench " HashSet" $ nf (deleteHS keysI) hsetOfHMs
404+ , bench " Set" $ nf (deleteS keysI) setOfHMs
405+ ]
406+ , bgroup " union"
407+ [ bench " List" $ whnf unionC listOfHMs
408+ , bench " Vector" $ whnf unionC vecOfHMs
409+ , bench " HashSet" $ whnf unionC hsetOfHMs
410+ , bench " Set" $ whnf unionC setOfHMs
411+ ]
412+ , bgroup " map"
413+ [ bench " List" $ nf (mapC (\ v -> v + 1 )) listOfHMs
414+ , bench " Vector" $ nf (mapC (\ v -> v + 1 )) vecOfHMs
415+ , bench " HashSet" $ nf (mapHS (\ v -> v + 1 )) hsetOfHMs
416+ , bench " Set" $ nf (mapS (\ v -> v + 1 )) setOfHMs
417+ ]
418+ , bgroup " intersection"
419+ [ bench " List" $ whnf intersectionC listOfHMs
420+ , bench " Vector" $ whnf intersectionC vecOfHMs
421+ , bench " HashSet" $ whnf intersectionC hsetOfHMs
422+ , bench " Set" $ whnf intersectionC setOfHMs
423+ ]
424+ , bgroup " size"
425+ [ bench " List" $ nf sizeC listOfHMs
426+ , bench " Vector" $ nf sizeC vecOfHMs
427+ , bench " HashSet" $ nf sizeHS hsetOfHMs
428+ , bench " Set" $ nf sizeS setOfHMs
429+ ]
430+ ]
431+
313432 -- Combine
314433 , bench " union" $ whnf (HM. union hmi) hmi2
315434
316435 -- Transformations
317436 , bench " map" $ whnf (HM. map (\ v -> v + 1 )) hmi
318437
319- -- * Difference and intersection
438+ -- Difference and intersection
320439 , bench " difference" $ whnf (HM. difference hmi) hmi2
321440 , bench " intersection" $ whnf (HM. intersection hmi) hmi2
322441
@@ -374,6 +493,18 @@ lookup xs m = foldl' (\z k -> fromMaybe z (HM.lookup k m)) 0 xs
374493{-# SPECIALIZE lookup :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
375494 -> Int #-}
376495
496+ lookupC :: (Eq k , Hashable k , Traversable f ) => [k ] -> f (HM. HashMap k Int ) -> f Int
497+ lookupC = fmap . lookup
498+ {-# SPECIALIZE lookupC :: [Int] -> [HM.HashMap Int Int] -> [Int] #-}
499+ {-# SPECIALIZE lookupC :: [Int] -> V.Vector (HM.HashMap Int Int)
500+ -> V.Vector Int #-}
501+
502+ lookupHS :: [Int ] -> HS. HashSet (HM. HashMap Int Int ) -> HS. HashSet Int
503+ lookupHS = HS. map . lookup
504+
505+ lookupS :: [Int ] -> S. Set (HM. HashMap Int Int ) -> S. Set Int
506+ lookupS = S. map . lookup
507+
377508insert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
378509 -> HM. HashMap k Int
379510insert xs m0 = foldl' (\ m (k, v) -> HM. insert k v m) m0 xs
@@ -384,6 +515,21 @@ insert xs m0 = foldl' (\m (k, v) -> HM.insert k v m) m0 xs
384515{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
385516 -> HM.HashMap BS.ByteString Int #-}
386517
518+ insertC :: (Eq k , Hashable k , Traversable f ) => [(k , Int )] -> f (HM. HashMap k Int )
519+ -> f (HM. HashMap k Int )
520+ insertC l = fmap (insert l)
521+ {-# SPECIALIZE insertC :: [(Int, Int)] -> [HM.HashMap Int Int]
522+ -> [HM.HashMap Int Int] #-}
523+ {-# SPECIALIZE insertC :: [(Int, Int)] -> V.Vector (HM.HashMap Int Int)
524+ -> V.Vector (HM.HashMap Int Int) #-}
525+
526+ insertHS :: [(Int , Int )] -> HS. HashSet (HM. HashMap Int Int )
527+ -> HS. HashSet (HM. HashMap Int Int )
528+ insertHS l = HS. map (insert l)
529+
530+ insertS :: [(Int , Int )] -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
531+ insertS l = S. map (insert l)
532+
387533delete :: (Eq k , Hashable k ) => [k ] -> HM. HashMap k Int -> HM. HashMap k Int
388534delete xs m0 = foldl' (\ m k -> HM. delete k m) m0 xs
389535{-# SPECIALIZE delete :: [Int] -> HM.HashMap Int Int -> HM.HashMap Int Int #-}
@@ -392,6 +538,21 @@ delete xs m0 = foldl' (\m k -> HM.delete k m) m0 xs
392538{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
393539 -> HM.HashMap BS.ByteString Int #-}
394540
541+ deleteC :: (Eq k , Hashable k , Functor f ) => [k ] -> f (HM. HashMap k Int )
542+ -> f (HM. HashMap k Int )
543+ deleteC = fmap . delete
544+ {-# SPECIALIZE deleteC :: [Int] -> [HM.HashMap Int Int]
545+ -> [HM.HashMap Int Int] #-}
546+ {-# SPECIALIZE deleteC :: [Int] -> V.Vector (HM.HashMap Int Int)
547+ -> V.Vector (HM.HashMap Int Int) #-}
548+
549+ deleteHS :: [Int ] -> HS. HashSet (HM. HashMap Int Int )
550+ -> HS. HashSet (HM. HashMap Int Int )
551+ deleteHS = HS. map . delete
552+
553+ deleteS :: [Int ] -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
554+ deleteS = S. map . delete
555+
395556alterInsert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
396557 -> HM. HashMap k Int
397558alterInsert xs m0 =
@@ -436,6 +597,52 @@ alterFDelete xs m0 =
436597{-# SPECIALIZE alterFDelete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
437598 -> HM.HashMap BS.ByteString Int #-}
438599
600+ unionC :: (Eq k , Hashable k , Foldable f ) => f (HM. HashMap k Int )
601+ -> HM. HashMap k Int
602+ unionC = foldl' HM. union mempty
603+ {-# SPECIALIZE unionC :: [HM.HashMap Int Int] -> HM.HashMap Int Int #-}
604+ {-# SPECIALIZE unionC :: V.Vector (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
605+ {-# SPECIALIZE unionC :: HS.HashSet (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
606+ {-# SPECIALIZE unionC :: S.Set (HM.HashMap Int Int) -> HM.HashMap Int Int #-}
607+
608+ mapC :: (Eq k , Hashable k , Functor f ) => (Int -> Int ) -> f (HM. HashMap k Int )
609+ -> f (HM. HashMap k Int )
610+ mapC f = fmap (HM. map f)
611+ {-# SPECIALIZE mapC :: (Int -> Int) -> [HM.HashMap Int Int]
612+ -> [HM.HashMap Int Int] #-}
613+ {-# SPECIALIZE mapC :: (Int -> Int) -> V.Vector (HM.HashMap Int Int)
614+ -> V.Vector (HM.HashMap Int Int) #-}
615+
616+ mapHS :: (Int -> Int ) -> HS. HashSet (HM. HashMap Int Int )
617+ -> HS. HashSet (HM. HashMap Int Int )
618+ mapHS f = HS. map (HM. map f)
619+
620+ mapS :: (Int -> Int ) -> S. Set (HM. HashMap Int Int ) -> S. Set (HM. HashMap Int Int )
621+ mapS f = S. map (HM. map f)
622+
623+ intersectionC :: (Eq k , Hashable k , Foldable f ) => f (HM. HashMap k Int )
624+ -> HM. HashMap k Int
625+ intersectionC = foldl' HM. intersection mempty
626+ {-# SPECIALIZE intersectionC :: [HM.HashMap Int Int]
627+ -> HM.HashMap Int Int #-}
628+ {-# SPECIALIZE intersectionC :: V.Vector (HM.HashMap Int Int)
629+ -> HM.HashMap Int Int #-}
630+ {-# SPECIALIZE intersectionC :: HS.HashSet (HM.HashMap Int Int)
631+ -> HM.HashMap Int Int #-}
632+ {-# SPECIALIZE intersectionC :: S.Set (HM.HashMap Int Int)
633+ -> HM.HashMap Int Int #-}
634+
635+ sizeC :: (Eq k , Hashable k , Functor f ) => f (HM. HashMap k Int ) -> f Int
636+ sizeC = fmap HM. size
637+ {-# SPECIALIZE sizeC :: [HM.HashMap Int Int] -> [Int] #-}
638+ {-# SPECIALIZE sizeC :: V.Vector (HM.HashMap Int Int) -> V.Vector Int #-}
639+
640+ sizeHS :: HS. HashSet (HM. HashMap Int Int ) -> HS. HashSet Int
641+ sizeHS = HS. map HM. size
642+
643+ sizeS :: S. Set (HM. HashMap Int Int ) -> S. Set Int
644+ sizeS = S. map HM. size
645+
439646isSubmapOfNaive :: (Eq k , Hashable k ) => HM. HashMap k Int -> HM. HashMap k Int -> Bool
440647isSubmapOfNaive m1 m2 = and [ Just v1 == HM. lookup k1 m2 | (k1,v1) <- HM. toList m1 ]
441648{-# SPECIALIZE isSubmapOfNaive :: HM.HashMap Int Int -> HM.HashMap Int Int -> Bool #-}
0 commit comments