@@ -10,8 +10,11 @@ import Data.Hashable (Hashable, hash)
10
10
import qualified Data.ByteString as BS
11
11
import qualified "hashmap" Data.HashMap as IHM
12
12
import qualified Data.HashMap.Strict as HM
13
+ import qualified "unordered-containers" Data.HashSet as HS
13
14
import qualified Data.IntMap as IM
14
15
import qualified Data.Map as M
16
+ import qualified Data.Set as S
17
+ import qualified Data.Vector as V
15
18
import Data.List (foldl' )
16
19
import Data.Maybe (fromMaybe )
17
20
import GHC.Generics (Generic )
@@ -36,6 +39,8 @@ instance NFData B where
36
39
data Env = Env {
37
40
n :: ! Int ,
38
41
42
+ csz :: ! Int , -- container size
43
+
39
44
elems :: ! [(String , Int )],
40
45
keys :: ! [String ],
41
46
elemsBS :: ! [(BS. ByteString , Int )],
@@ -48,6 +53,11 @@ data Env = Env {
48
53
keysBS' :: ! [BS. ByteString ],
49
54
keysI' :: ! [Int ],
50
55
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
+
51
61
keysDup :: ! [String ],
52
62
keysDupBS :: ! [BS. ByteString ],
53
63
keysDupI :: ! [Int ],
@@ -78,6 +88,20 @@ setupEnv :: IO Env
78
88
setupEnv = do
79
89
let n = 2 ^ (12 :: Int )
80
90
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
+
81
105
elems = zip keys [1 .. n]
82
106
keys = US. rnd 8 n
83
107
elemsBS = zip keysBS [1 .. n]
@@ -90,6 +114,11 @@ setupEnv = do
90
114
keysBS' = UBS. rnd' 8 n
91
115
keysI' = UI. rnd' (n+ n) n
92
116
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
+
93
122
keysDup = US. rnd 2 n
94
123
keysDupBS = UBS. rnd 2 n
95
124
keysDupI = UI. rnd (n`div` 4 ) n
@@ -126,8 +155,8 @@ main = do
126
155
defaultMain
127
156
[
128
157
env setupEnv $ \ ~ (Env {.. }) ->
129
- -- * Comparison to other data structures
130
- -- ** Map
158
+ -- Comparison to other data structures
159
+ -- Map
131
160
bgroup " Map"
132
161
[ bgroup " lookup"
133
162
[ bench " String" $ whnf (lookupM keys) m
@@ -167,7 +196,7 @@ main = do
167
196
]
168
197
]
169
198
170
- -- ** Map from the hashmap package
199
+ -- Map from the hashmap package
171
200
, env setupEnv $ \ ~ (Env {.. }) ->
172
201
bgroup " hashmap/Map"
173
202
[ bgroup " lookup"
@@ -212,7 +241,7 @@ main = do
212
241
]
213
242
]
214
243
215
- -- ** IntMap
244
+ -- IntMap
216
245
, env setupEnv $ \ ~ (Env {.. }) ->
217
246
bgroup " IntMap"
218
247
[ bench " lookup" $ whnf (lookupIM keysI) im
@@ -228,7 +257,7 @@ main = do
228
257
229
258
, env setupEnv $ \ ~ (Env {.. }) ->
230
259
bgroup " HashMap"
231
- [ -- * Basic interface
260
+ [ -- Basic interface
232
261
bgroup " lookup"
233
262
[ bench " String" $ whnf (lookup keys) hm
234
263
, bench " ByteString" $ whnf (lookup keysBS) hmbs
@@ -310,13 +339,103 @@ main = do
310
339
, bench " Int" $ whnf (isSubmapOfNaive hmiSubset) hmi
311
340
]
312
341
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
+
313
432
-- Combine
314
433
, bench " union" $ whnf (HM. union hmi) hmi2
315
434
316
435
-- Transformations
317
436
, bench " map" $ whnf (HM. map (\ v -> v + 1 )) hmi
318
437
319
- -- * Difference and intersection
438
+ -- Difference and intersection
320
439
, bench " difference" $ whnf (HM. difference hmi) hmi2
321
440
, bench " intersection" $ whnf (HM. intersection hmi) hmi2
322
441
@@ -374,6 +493,18 @@ lookup xs m = foldl' (\z k -> fromMaybe z (HM.lookup k m)) 0 xs
374
493
{-# SPECIALIZE lookup :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
375
494
-> Int #-}
376
495
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
+
377
508
insert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
378
509
-> HM. HashMap k Int
379
510
insert 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
384
515
{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
385
516
-> HM.HashMap BS.ByteString Int #-}
386
517
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
+
387
533
delete :: (Eq k , Hashable k ) => [k ] -> HM. HashMap k Int -> HM. HashMap k Int
388
534
delete xs m0 = foldl' (\ m k -> HM. delete k m) m0 xs
389
535
{-# 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
392
538
{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
393
539
-> HM.HashMap BS.ByteString Int #-}
394
540
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
+
395
556
alterInsert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
396
557
-> HM. HashMap k Int
397
558
alterInsert xs m0 =
@@ -436,6 +597,52 @@ alterFDelete xs m0 =
436
597
{-# SPECIALIZE alterFDelete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
437
598
-> HM.HashMap BS.ByteString Int #-}
438
599
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
+
439
646
isSubmapOfNaive :: (Eq k , Hashable k ) => HM. HashMap k Int -> HM. HashMap k Int -> Bool
440
647
isSubmapOfNaive m1 m2 = and [ Just v1 == HM. lookup k1 m2 | (k1,v1) <- HM. toList m1 ]
441
648
{-# SPECIALIZE isSubmapOfNaive :: HM.HashMap Int Int -> HM.HashMap Int Int -> Bool #-}
0 commit comments