-
Notifications
You must be signed in to change notification settings - Fork 100
/
Copy pathStats.hs
69 lines (60 loc) · 2.31 KB
/
Stats.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -funbox-strict-fields #-}
module Stats where
import Data.HashMap.Internal (HashMap (..))
import Data.Semigroup
import qualified Data.HashMap.Internal as HM
import qualified Data.HashMap.Internal.Array as A
data Histogram = H {
empty :: !Int
, leaf :: !Int
, bitmapIndexed :: !Int
, full :: !Int
, collision :: !Int
} deriving Show
instance Semigroup Histogram where
h1 <> h2 = H {
empty = empty h1 + empty h2
, leaf = leaf h1 + leaf h2
, bitmapIndexed = bitmapIndexed h1 + bitmapIndexed h2
, full = full h1 + full h2
, collision = collision h1 + collision h2
}
instance Monoid Histogram where
mempty = H 0 0 0 0 0
-- | Count the number of node types at each level
nodeHistogram :: HM.HashMap k v -> [Histogram]
nodeHistogram Empty = [mempty { empty = 1 }]
nodeHistogram (Leaf {}) = [mempty { leaf = 1 }]
nodeHistogram (BitmapIndexed _ ary) =
mempty { bitmapIndexed = 1 } :
A.foldl' (\ xs -> zipWith_ merge xs . nodeHistogram) [] ary
nodeHistogram (Full ary) =
mempty { full = 1 } :
A.foldl' (\ xs -> zipWith_ merge xs . nodeHistogram) [] ary
nodeHistogram (Collision {}) = [mempty { collision = 1 }]
merge (Just h1) (Just h2) = h1 `mappend` h2
merge (Just h) Nothing = h `mappend` mempty
merge Nothing (Just h) = mempty `mappend` h
merge Nothing Nothing = error "impossible"
zipWith_ :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c]
zipWith_ f = go
where
go [] [] = []
go [] (y:ys) = let z = f Nothing (Just y) in z `seq` (z : go [] ys)
go (x:xs) [] = let z = f (Just x) Nothing in z `seq` (z : go xs [])
go (x:xs) (y:ys) = let z = f (Just x) (Just y) in z `seq` (z : go xs ys)
{-# INLINE zipWith_ #-}
ppHistogram :: [Histogram] -> String
ppHistogram = go 0
where
go _ [] = ""
go lvl ((H {..}):hs) =
indent ++ "empty: " ++ show empty ++ "\n" ++
indent ++ "leaf: " ++ show leaf ++ "\n" ++
indent ++ "bitmapIndexed: " ++ show bitmapIndexed ++ "\n" ++
indent ++ "full: " ++ show full ++ "\n" ++
indent ++ "collision: " ++ show collision ++ "\n" ++
go (lvl+2) hs
where indent = replicate lvl ' '