@@ -20,8 +20,16 @@ import Test.Tasty.Bench (bench, bgroup, defaultMain, env, nf, whnf)
20
20
import qualified Data.ByteString as BS
21
21
import qualified "hashmap" Data.HashMap as IHM
22
22
import qualified Data.HashMap.Strict as HM
23
+ import qualified "unordered-containers" Data.HashSet as HS
23
24
import qualified Data.IntMap as IM
25
+ import Data.List (foldl' )
24
26
import 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
+
25
33
import qualified Util.ByteString as UBS
26
34
import qualified Util.Int as UI
27
35
import qualified Util.String as US
@@ -37,6 +45,8 @@ instance NFData B where
37
45
data Env = Env {
38
46
n :: ! Int ,
39
47
48
+ csz :: ! Int , -- container size
49
+
40
50
elems :: ! [(String , Int )],
41
51
keys :: ! [String ],
42
52
elemsBS :: ! [(BS. ByteString , Int )],
@@ -49,6 +59,11 @@ data Env = Env {
49
59
keysBS' :: ! [BS. ByteString ],
50
60
keysI' :: ! [Int ],
51
61
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
+
52
67
keysDup :: ! [String ],
53
68
keysDupBS :: ! [BS. ByteString ],
54
69
keysDupI :: ! [Int ],
@@ -79,6 +94,20 @@ setupEnv :: IO Env
79
94
setupEnv = do
80
95
let n = 2 ^ (12 :: Int )
81
96
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
+
82
111
elems = zip keys [1 .. n]
83
112
keys = US. rnd 8 n
84
113
elemsBS = zip keysBS [1 .. n]
@@ -91,6 +120,11 @@ setupEnv = do
91
120
keysBS' = UBS. rnd' 8 n
92
121
keysI' = UI. rnd' (n+ n) n
93
122
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
+
94
128
keysDup = US. rnd 2 n
95
129
keysDupBS = UBS. rnd 2 n
96
130
keysDupI = UI. rnd (n`div` 4 ) n
@@ -128,8 +162,8 @@ main = do
128
162
[
129
163
#ifdef BENCH_containers_Map
130
164
env setupEnv $ \ ~ (Env {.. }) ->
131
- -- * Comparison to other data structures
132
- -- ** Map
165
+ -- Comparison to other data structures
166
+ -- Map
133
167
bgroup " Map"
134
168
[ bgroup " lookup"
135
169
[ bench " String" $ whnf (lookupM keys) m
@@ -231,7 +265,7 @@ main = do
231
265
232
266
env setupEnv $ \ ~ (Env {.. }) ->
233
267
bgroup " HashMap"
234
- [ -- * Basic interface
268
+ [ -- Basic interface
235
269
bgroup " lookup"
236
270
[ bench " String" $ whnf (lookup keys) hm
237
271
, bench " ByteString" $ whnf (lookup keysBS) hmbs
@@ -313,6 +347,51 @@ main = do
313
347
, bench " Int" $ whnf (isSubmapOfNaive hmiSubset) hmi
314
348
]
315
349
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
+
316
395
-- Combine
317
396
, bgroup " union"
318
397
[ bench " Int" $ whnf (HM. union hmi) hmi2
@@ -327,7 +406,7 @@ main = do
327
406
-- Transformations
328
407
, bench " map" $ whnf (HM. map (\ v -> v + 1 )) hmi
329
408
330
- -- * Difference and intersection
409
+ -- Difference and intersection
331
410
, bench " difference" $ whnf (HM. difference hmi) hmi2
332
411
333
412
-- Folds
@@ -389,6 +468,18 @@ lookup xs m = foldl' (\z k -> fromMaybe z (HM.lookup k m)) 0 xs
389
468
{-# SPECIALIZE lookup :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
390
469
-> Int #-}
391
470
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
+
392
483
insert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
393
484
-> HM. HashMap k Int
394
485
insert 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
399
490
{-# SPECIALIZE insert :: [(BS.ByteString, Int)] -> HM.HashMap BS.ByteString Int
400
491
-> HM.HashMap BS.ByteString Int #-}
401
492
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
+
402
508
delete :: (Eq k , Hashable k ) => [k ] -> HM. HashMap k Int -> HM. HashMap k Int
403
509
delete xs m0 = foldl' (\ m k -> HM. delete k m) m0 xs
404
510
{-# 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
407
513
{-# SPECIALIZE delete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
408
514
-> HM.HashMap BS.ByteString Int #-}
409
515
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
+
410
531
alterInsert :: (Eq k , Hashable k ) => [(k , Int )] -> HM. HashMap k Int
411
532
-> HM. HashMap k Int
412
533
alterInsert xs m0 =
@@ -451,6 +572,52 @@ alterFDelete xs m0 =
451
572
{-# SPECIALIZE alterFDelete :: [BS.ByteString] -> HM.HashMap BS.ByteString Int
452
573
-> HM.HashMap BS.ByteString Int #-}
453
574
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
+
454
621
isSubmapOfNaive :: (Eq k , Hashable k ) => HM. HashMap k Int -> HM. HashMap k Int -> Bool
455
622
isSubmapOfNaive m1 m2 = and [ Just v1 == HM. lookup k1 m2 | (k1,v1) <- HM. toList m1 ]
456
623
{-# SPECIALIZE isSubmapOfNaive :: HM.HashMap Int Int -> HM.HashMap Int Int -> Bool #-}
0 commit comments