@@ -0,0 +1,115 @@
1+{-# LANGUAGE BangPatterns, OverloadedStrings, FlexibleInstances, MultiParamTypeClasses, DataKinds #-}
2+
3+import Control.DeepSeq
4+import Criterion.Main
5+import Data.Aeson
6+import Data.Aeson.Types (Parser)
7+import Data.Hashable
8+import qualified Data.ByteString.Lazy as LBS
9+import qualified Data.Text as T
10+import qualified Data.Map as M
11+import qualified Data.HashMap.Strict as HM
12+
13+value :: Int -> HM.HashMap T.Text T.Text
14+value n = HM.fromList $ map f [1..n]
15+ where
16+ f m = let t = T.pack (show m) in (t, t)
17+
18+newtype T1 = T1 T.Text
19+ deriving (Eq, Ord)
20+
21+instance NFData T1 where
22+ rnf (T1 t) = rnf t
23+instance Hashable T1 where
24+ hashWithSalt salt (T1 t) = hashWithSalt salt t
25+instance FromJSONKey T1 'JSONKeyIdentity where
26+ fromJSONKey _ = T1
27+
28+newtype T2 = T2 T.Text
29+ deriving (Eq, Ord)
30+
31+instance NFData T2 where
32+ rnf (T2 t) = rnf t
33+instance Hashable T2 where
34+ hashWithSalt salt (T2 t) = hashWithSalt salt t
35+instance FromJSONKey T2 'JSONKeyCoerce where
36+ fromJSONKey _ = ()
37+
38+newtype T3 = T3 T.Text
39+ deriving (Eq, Ord)
40+
41+instance NFData T3 where
42+ rnf (T3 t) = rnf t
43+instance Hashable T3 where
44+ hashWithSalt salt (T3 t) = hashWithSalt salt t
45+instance FromJSONKey T3 'JSONKeyTextParser where
46+ fromJSONKey _ = return . T3
47+
48+encodedValue10 :: LBS.ByteString
49+encodedValue10 = encode $ value 10
50+
51+encodedValue100 :: LBS.ByteString
52+encodedValue100 = encode $ value 100
53+
54+encodedValue1000 :: LBS.ByteString
55+encodedValue1000 = encode $ value 1000
56+
57+encodedValue10000 :: LBS.ByteString
58+encodedValue10000 = encode $ value 10000
59+
60+main :: IO ()
61+main = do
62+ defaultMain
63+ [ bgroup "HashMap"
64+ [ bgroup "10"
65+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T.Text T.Text)) encodedValue10
66+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T1 T.Text)) encodedValue10
67+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T2 T.Text)) encodedValue10
68+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T3 T.Text)) encodedValue10
69+ ]
70+ , bgroup "100"
71+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T.Text T.Text)) encodedValue100
72+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T1 T.Text)) encodedValue100
73+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T2 T.Text)) encodedValue100
74+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T3 T.Text)) encodedValue100
75+ ]
76+ , bgroup "1000"
77+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T.Text T.Text)) encodedValue1000
78+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T1 T.Text)) encodedValue1000
79+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T2 T.Text)) encodedValue1000
80+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T3 T.Text)) encodedValue1000
81+ ]
82+ , bgroup "10000"
83+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T.Text T.Text)) encodedValue10000
84+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T1 T.Text)) encodedValue10000
85+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T2 T.Text)) encodedValue10000
86+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (HM.HashMap T3 T.Text)) encodedValue10000
87+ ]
88+ ]
89+ , bgroup "Map"
90+ [ bgroup "10"
91+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T.Text T.Text)) encodedValue10
92+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T1 T.Text)) encodedValue10
93+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T2 T.Text)) encodedValue10
94+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T3 T.Text)) encodedValue10
95+ ]
96+ , bgroup "100"
97+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T.Text T.Text)) encodedValue100
98+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T1 T.Text)) encodedValue100
99+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T2 T.Text)) encodedValue100
100+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T3 T.Text)) encodedValue100
101+ ]
102+ , bgroup "1000"
103+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T.Text T.Text)) encodedValue1000
104+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T1 T.Text)) encodedValue1000
105+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T2 T.Text)) encodedValue1000
106+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T3 T.Text)) encodedValue1000
107+ ]
108+ , bgroup "10000"
109+ [ bench "Text" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T.Text T.Text)) encodedValue10000
110+ , bench "Identity" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T1 T.Text)) encodedValue10000
111+ , bench "Coerce" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T2 T.Text)) encodedValue10000
112+ , bench "Parser" $ nf (decode :: LBS.ByteString -> Maybe (M.Map T3 T.Text)) encodedValue10000
113+ ]
114+ ]
115+ ]