on master help sign in
Add flag for benchmarks to select local or external aeson dependency
3971ed9lyxia
benchmarks/AesonFoldable.hs+13−41
@@ -1,5 +1,4 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE PackageImports #-}
3
2
4module Main (main) where
3module Main (main) where
5
4
@@ -9,8 +8,7 @@ import Prelude ()
9import Prelude.Compat
8import Prelude.Compat
10
9
11import Data.Foldable (toList)
10import Data.Foldable (toList)
12−import qualified "aeson" Data.Aeson as A
11+import qualified Data.Aeson as A
13−import qualified "aeson-benchmarks" Data.Aeson as B
14import qualified Data.Sequence as S
12import qualified Data.Sequence as S
15import qualified Data.Vector as V
13import qualified Data.Vector as V
16import qualified Data.Vector.Unboxed as U
14import qualified Data.Vector.Unboxed as U
@@ -21,10 +19,6 @@ import qualified Data.Vector.Unboxed as U
21
19
22newtype L f = L { getL :: f Int }
20newtype L f = L { getL :: f Int }
23
21
24−instance Foldable f => B.ToJSON (L f) where
25− toJSON = error "do not use this"
26− toEncoding = B.toEncoding . toList . getL
27−
28instance Foldable f => A.ToJSON (L f) where
22instance Foldable f => A.ToJSON (L f) where
29 toJSON = error "do not use this"
23 toJSON = error "do not use this"
30 toEncoding = A.toEncoding . toList . getL
24 toEncoding = A.toEncoding . toList . getL
@@ -35,10 +29,6 @@ instance Foldable f => A.ToJSON (L f) where
35
29
36newtype F f = F { getF :: f Int }
30newtype F f = F { getF :: f Int }
37
31
38−instance Foldable f => B.ToJSON (F f) where
39− toJSON = error "do not use this"
40− toEncoding = B.foldable . getF
41−
42instance Foldable f => A.ToJSON (F f) where
32instance Foldable f => A.ToJSON (F f) where
43 toJSON = error "do not use this"
33 toJSON = error "do not use this"
44 toEncoding = A.foldable . getF
34 toEncoding = A.foldable . getF
@@ -63,52 +53,34 @@ valueUVector = U.fromList valueList
63-- Main
53-- Main
64-------------------------------------------------------------------------------
54-------------------------------------------------------------------------------
65
55
66−benchEncodeA
56+benchEncode
67 :: A.ToJSON a
57 :: A.ToJSON a
68 => String
58 => String
69 -> a
59 -> a
70 -> Benchmark
60 -> Benchmark
71−benchEncodeA name val
61+benchEncode name val
72 = bench ("A " ++ name) $ nf A.encode val
62 = bench ("A " ++ name) $ nf A.encode val
73
63
74−benchEncodeB
75− :: B.ToJSON a
76− => String
77− -> a
78− -> Benchmark
79−benchEncodeB name val
80− = bench ("B " ++ name) $ nf B.encode val
81−
82main :: IO ()
64main :: IO ()
83main = defaultMain
65main = defaultMain
84 [ bgroup "encode"
66 [ bgroup "encode"
85 [ bgroup "List"
67 [ bgroup "List"
86− [ benchEncodeB "-" valueList
87− , benchEncodeB "L" $ L valueList
88− , benchEncodeB "F" $ F valueList
89− , benchEncodeA "-" valueList
68+ [ benchEncode "-" valueList
90− , benchEncodeA "L" $ L valueList
69+ , benchEncode "L" $ L valueList
91− , benchEncodeA "F" $ F valueList
70+ , benchEncode "F" $ F valueList
92 ]
71 ]
93 , bgroup "Seq"
72 , bgroup "Seq"
94− [ benchEncodeB "-" valueSeq
95− , benchEncodeB "L" $ L valueSeq
96− , benchEncodeB "F" $ F valueSeq
97− , benchEncodeA "-" valueSeq
73+ [ benchEncode "-" valueSeq
98− , benchEncodeA "L" $ L valueSeq
74+ , benchEncode "L" $ L valueSeq
99− , benchEncodeA "F" $ F valueSeq
75+ , benchEncode "F" $ F valueSeq
100 ]
76 ]
101 , bgroup "Vector"
77 , bgroup "Vector"
102− [ benchEncodeB "-" valueVector
103− , benchEncodeB "L" $ L valueVector
104− , benchEncodeB "F" $ F valueVector
105− , benchEncodeA "-" valueVector
78+ [ benchEncode "-" valueVector
106− , benchEncodeA "L" $ L valueVector
79+ , benchEncode "L" $ L valueVector
107− , benchEncodeA "F" $ F valueVector
80+ , benchEncode "F" $ F valueVector
108 ]
81 ]
109 , bgroup "Vector.Unboxed"
82 , bgroup "Vector.Unboxed"
110− [ benchEncodeB "-" valueUVector
111− , benchEncodeA "-" valueUVector
83+ [ benchEncode "-" valueUVector
112 ]
84 ]
113 ]
85 ]
114 ]
86 ]
benchmarks/AesonMap.hs+38−54
@@ -1,5 +1,4 @@
1{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE PackageImports #-}
2{-# LANGUAGE PackageImports #-}
4{-# LANGUAGE RankNTypes #-}
3{-# LANGUAGE RankNTypes #-}
5
4
@@ -15,9 +14,8 @@ import Criterion.Main
15import Data.Hashable
14import Data.Hashable
16import Data.Proxy (Proxy (..))
15import Data.Proxy (Proxy (..))
17import Data.Tagged (Tagged (..))
16import Data.Tagged (Tagged (..))
18−import qualified "aeson" Data.Aeson as A
17+import Data.Aeson
19−import qualified "aeson-benchmarks" Data.Aeson as B
20−import qualified "aeson-benchmarks" Data.Aeson.Types as B (fromJSONKeyCoerce)
18+import Data.Aeson.Types (fromJSONKeyCoerce)
21import qualified Data.ByteString.Lazy as LBS
19import qualified Data.ByteString.Lazy as LBS
22import qualified Data.HashMap.Strict as HM
20import qualified Data.HashMap.Strict as HM
23import qualified Data.Map as M
21import qualified Data.Map as M
@@ -47,10 +45,10 @@ instance NFData T1 where
47instance Hashable T1 where
45instance Hashable T1 where
48 hashWithSalt salt (T1 t) = hashWithSalt salt t
46 hashWithSalt salt (T1 t) = hashWithSalt salt t
49
47
50−instance B.FromJSON T1 where
48+instance FromJSON T1 where
51− parseJSON = B.withText "T1" $ pure . T1
49+ parseJSON = withText "T1" $ pure . T1
52−instance B.FromJSONKey T1 where
50+instance FromJSONKey T1 where
53− fromJSONKey = B.FromJSONKeyText T1
51+ fromJSONKey = FromJSONKeyText T1
54
52
55-------------------------------------------------------------------------------
53-------------------------------------------------------------------------------
56-- Coerce
54-- Coerce
@@ -64,10 +62,10 @@ instance NFData T2 where
64instance Hashable T2 where
62instance Hashable T2 where
65 hashWithSalt salt (T2 t) = hashWithSalt salt t
63 hashWithSalt salt (T2 t) = hashWithSalt salt t
66
64
67−instance B.FromJSON T2 where
65+instance FromJSON T2 where
68− parseJSON = B.withText "T2" $ pure . T2
66+ parseJSON = withText "T2" $ pure . T2
69−instance B.FromJSONKey T2 where
67+instance FromJSONKey T2 where
70− fromJSONKey = B.fromJSONKeyCoerce
68+ fromJSONKey = fromJSONKeyCoerce
71
69
72-------------------------------------------------------------------------------
70-------------------------------------------------------------------------------
73-- TextParser
71-- TextParser
@@ -81,10 +79,10 @@ instance NFData T3 where
81instance Hashable T3 where
79instance Hashable T3 where
82 hashWithSalt salt (T3 t) = hashWithSalt salt t
80 hashWithSalt salt (T3 t) = hashWithSalt salt t
83
81
84−instance B.FromJSON T3 where
82+instance FromJSON T3 where
85− parseJSON = B.withText "T3" $ pure . T3
83+ parseJSON = withText "T3" $ pure . T3
86−instance B.FromJSONKey T3 where
84+instance FromJSONKey T3 where
87− fromJSONKey = B.FromJSONKeyTextParser (pure . T3)
85+ fromJSONKey = FromJSONKeyTextParser (pure . T3)
88
86
89-------------------------------------------------------------------------------
87-------------------------------------------------------------------------------
90-- Values
88-- Values
@@ -97,40 +95,30 @@ value1000 = value 1000
97value10000 = value 10000
95value10000 = value 10000
98
96
99encodedValue10 :: LBS.ByteString
97encodedValue10 :: LBS.ByteString
100−encodedValue10 = B.encode value10
98+encodedValue10 = encode value10
101
99
102encodedValue100 :: LBS.ByteString
100encodedValue100 :: LBS.ByteString
103−encodedValue100 = B.encode value100
101+encodedValue100 = encode value100
104
102
105encodedValue1000 :: LBS.ByteString
103encodedValue1000 :: LBS.ByteString
106−encodedValue1000 = B.encode value1000
104+encodedValue1000 = encode value1000
107
105
108encodedValue10000 :: LBS.ByteString
106encodedValue10000 :: LBS.ByteString
109−encodedValue10000 = B.encode value10000
107+encodedValue10000 = encode value10000
110
108
111-------------------------------------------------------------------------------
109-------------------------------------------------------------------------------
112-- Helpers
110-- Helpers
113-------------------------------------------------------------------------------
111-------------------------------------------------------------------------------
114
112
115−decodeHMB
113+decodeHM
116− :: (B.FromJSONKey k, Eq k, Hashable k)
114+ :: (FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)
117 => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
115 => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
118−decodeHMB _ = B.decode
116+decodeHM _ = decode
119
117
120−decodeHMA
118+decodeMap
121− :: (A.FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)
122− => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
123−decodeHMA _ = A.decode
124−
125−decodeMapB
126− :: (B.FromJSONKey k, Ord k)
127− => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
128−decodeMapB _ = B.decode
129−
130−decodeMapA
131− :: (A.FromJSON (M.Map k T.Text), Ord k)
119+ :: (FromJSON (M.Map k T.Text), Ord k)
132 => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
120 => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
133−decodeMapA _ = A.decode
121+decodeMap _ = decode
134
122
135proxyText :: Proxy T.Text
123proxyText :: Proxy T.Text
136proxyText = Proxy
124proxyText = Proxy
@@ -156,15 +144,14 @@ benchDecodeHM
156 -> LBS.ByteString
144 -> LBS.ByteString
157 -> Benchmark
145 -> Benchmark
158benchDecodeHM name val = bgroup name
146benchDecodeHM name val = bgroup name
159− [ bench "Text" $ nf (decodeHMB proxyText) val
147+ [ bench "Text" $ nf (decodeHM proxyText) val
160− , bench "Identity" $ nf (decodeHMB proxyT1) val
148+ , bench "Identity" $ nf (decodeHM proxyT1) val
161− , bench "Coerce" $ nf (decodeHMB proxyT2) val
149+ , bench "Coerce" $ nf (decodeHM proxyT2) val
162− , bench "Parser" $ nf (decodeHMB proxyT3) val
150+ , bench "Parser" $ nf (decodeHM proxyT3) val
163− , bench "aeson-hackage" $ nf (decodeHMA proxyText) val
164− , bench "Tagged Text" $ nf (decodeHMB $ proxyTagged proxyText) val
151+ , bench "Tagged Text" $ nf (decodeHM $ proxyTagged proxyText) val
165− , bench "Tagged Identity" $ nf (decodeHMB $ proxyTagged proxyT1) val
152+ , bench "Tagged Identity" $ nf (decodeHM $ proxyTagged proxyT1) val
166− , bench "Tagged Coerce" $ nf (decodeHMB $ proxyTagged proxyT2) val
153+ , bench "Tagged Coerce" $ nf (decodeHM $ proxyTagged proxyT2) val
167− , bench "Tagged Parser" $ nf (decodeHMB $ proxyTagged proxyT3) val
154+ , bench "Tagged Parser" $ nf (decodeHM $ proxyTagged proxyT3) val
168 ]
155 ]
169
156
170benchDecodeMap
157benchDecodeMap
@@ -172,11 +159,10 @@ benchDecodeMap
172 -> LBS.ByteString
159 -> LBS.ByteString
173 -> Benchmark
160 -> Benchmark
174benchDecodeMap name val = bgroup name
161benchDecodeMap name val = bgroup name
175− [ bench "Text" $ nf (decodeMapB proxyText) val
162+ [ bench "Text" $ nf (decodeMap proxyText) val
176− , bench "Identity" $ nf (decodeMapB proxyT1) val
163+ , bench "Identity" $ nf (decodeMap proxyT1) val
177− , bench "Coerce" $ nf (decodeMapB proxyT2) val
164+ , bench "Coerce" $ nf (decodeMap proxyT2) val
178− , bench "Parser" $ nf (decodeMapB proxyT3) val
165+ , bench "Parser" $ nf (decodeMap proxyT3) val
179− , bench "aeson-hackage" $ nf (decodeMapA proxyText) val
180 ]
166 ]
181
167
182benchEncodeHM
168benchEncodeHM
@@ -184,8 +170,7 @@ benchEncodeHM
184 -> HM.HashMap T.Text T.Text
170 -> HM.HashMap T.Text T.Text
185 -> Benchmark
171 -> Benchmark
186benchEncodeHM name val = bgroup name
172benchEncodeHM name val = bgroup name
187− [ bench "Text" $ nf B.encode val
173+ [ bench "Text" $ nf encode val
188− , bench "aeson-0.11" $ nf A.encode val
189 ]
174 ]
190
175
191benchEncodeMap
176benchEncodeMap
@@ -193,8 +178,7 @@ benchEncodeMap
193 -> HM.HashMap T.Text T.Text
178 -> HM.HashMap T.Text T.Text
194 -> Benchmark
179 -> Benchmark
195benchEncodeMap name val = bgroup name
180benchEncodeMap name val = bgroup name
196− [ bench "Text" $ nf B.encode val'
181+ [ bench "Text" $ nf encode val'
197− , bench "aeson-0.11" $ nf A.encode val'
198 ]
182 ]
199 where
183 where
200 val' :: M.Map T.Text T.Text
184 val' :: M.Map T.Text T.Text
benchmarks/AesonParse.hs+1−2
@@ -1,13 +1,12 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE PackageImports #-}
4
3
5module Main (main) where
4module Main (main) where
6
5
7import Prelude ()
6import Prelude ()
8import Prelude.Compat
7import Prelude.Compat
9
8
10−import "aeson-benchmarks" Data.Aeson
9+import Data.Aeson
11import Control.Monad
10import Control.Monad
12import Data.Attoparsec.ByteString (IResult(..), parseWith)
11import Data.Attoparsec.ByteString (IResult(..), parseWith)
13import Data.Time.Clock
12import Data.Time.Clock
benchmarks/Compare.hs+1−2
@@ -1,4 +1,3 @@
1−{-# LANGUAGE PackageImports #-}
2{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE ScopedTypeVariables #-}
3
2
4module Main (main) where
3module Main (main) where
@@ -14,7 +13,7 @@ import Data.Json.Builder
14import Twitter
13import Twitter
15import Twitter.Manual ()
14import Twitter.Manual ()
16import Typed.Common
15import Typed.Common
17−import qualified "aeson-benchmarks" Data.Aeson as Aeson
16+import qualified Data.Aeson as Aeson
18import qualified Compare.JsonBench as JsonBench
17import qualified Compare.JsonBench as JsonBench
19
18
20main :: IO ()
19main :: IO ()
benchmarks/CompareWithJSON.hs+20−31
@@ -1,4 +1,3 @@
1−{-# LANGUAGE PackageImports #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
1{-# OPTIONS_GHC -fno-warn-orphans #-}
3
2
4module Main (main) where
3module Main (main) where
@@ -11,10 +10,9 @@ import Blaze.ByteString.Builder.Char.Utf8 (fromString)
11import Control.DeepSeq (NFData(rnf))
10import Control.DeepSeq (NFData(rnf))
12import Criterion.Main
11import Criterion.Main
13import Data.Maybe (fromMaybe)
12import Data.Maybe (fromMaybe)
14−import qualified "aeson-benchmarks" Data.Aeson as A
13+import qualified Data.Aeson as A
15−import qualified "aeson-benchmarks" Data.Aeson.Text as A
14+import qualified Data.Aeson.Text as A
16−import qualified "aeson-benchmarks" Data.Aeson.Parser.Internal as I
15+import qualified Data.Aeson.Parser.Internal as I
17−import qualified "aeson" Data.Aeson as B
18import qualified Data.ByteString as BS
16import qualified Data.ByteString as BS
19import qualified Data.ByteString.Lazy as BL
17import qualified Data.ByteString.Lazy as BL
20import qualified Data.Text.Lazy as TL
18import qualified Data.Text.Lazy as TL
@@ -39,20 +37,14 @@ decodeJ s =
39 J.Ok v -> v
37 J.Ok v -> v
40 J.Error _ -> error "fail to parse via JSON"
38 J.Error _ -> error "fail to parse via JSON"
41
39
42−decodeA :: BL.ByteString -> A.Value
40+decode :: BL.ByteString -> A.Value
43−decodeA s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
41+decode s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
44
42
45−decodeA' :: BL.ByteString -> A.Value
43+decode' :: BL.ByteString -> A.Value
46−decodeA' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
44+decode' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
47
45
48−decodeAS :: BS.ByteString -> A.Value
46+decodeS :: BS.ByteString -> A.Value
49−decodeAS s = fromMaybe (error "fail to parse via Aeson") $ A.decodeStrict' s
47+decodeS s = fromMaybe (error "fail to parse via Aeson") $ A.decodeStrict' s
50−
51−decodeB :: BL.ByteString -> B.Value
52−decodeB s = fromMaybe (error "fail to parse via Aeson") $ B.decode s
53−
54−decodeBS :: BS.ByteString -> B.Value
55−decodeBS s = fromMaybe (error "fail to parse via Aeson") $ B.decodeStrict' s
56
48
57decodeIP :: BL.ByteString -> A.Value
49decodeIP :: BL.ByteString -> A.Value
58decodeIP s = fromMaybe (error "fail to parse via Parser.decodeWith") $
50decodeIP s = fromMaybe (error "fail to parse via Parser.decodeWith") $
@@ -80,32 +72,29 @@ main = do
80 defaultMain [
72 defaultMain [
81 bgroup "decode" [
73 bgroup "decode" [
82 bgroup "en" [
74 bgroup "en" [
83− bench "aeson/lazy" $ nf decodeA enA
75+ bench "aeson/lazy" $ nf decode enA
84− , bench "aeson/strict" $ nf decodeA' enA
76+ , bench "aeson/strict" $ nf decode' enA
85− , bench "aeson/stricter" $ nf decodeAS enS
77+ , bench "aeson/stricter" $ nf decodeS enS
86− , bench "aeson/hackage" $ nf decodeB enA
87− , bench "aeson/hackage'" $ nf decodeBS enS
88 , bench "aeson/parser" $ nf decodeIP enA
78 , bench "aeson/parser" $ nf decodeIP enA
89 , bench "json" $ nf decodeJ enJ
79 , bench "json" $ nf decodeJ enJ
90 ]
80 ]
91 , bgroup "jp" [
81 , bgroup "jp" [
92− bench "aeson" $ nf decodeA jpA
82+ bench "aeson" $ nf decode jpA
93− , bench "aeson/stricter" $ nf decodeAS jpS
83+ , bench "aeson/stricter" $ nf decodeS jpS
94− , bench "aeson/hackage" $ nf decodeB jpA
95 , bench "json" $ nf decodeJ jpJ
84 , bench "json" $ nf decodeJ jpJ
96 ]
85 ]
97 ]
86 ]
98 , bgroup "encode" [
87 , bgroup "encode" [
99 bgroup "en" [
88 bgroup "en" [
100− bench "aeson-to-bytestring" $ nf A.encode (decodeA enA)
89+ bench "aeson-to-bytestring" $ nf A.encode (decode enA)
101− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA enA)
90+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode enA)
102− , bench "aeson-to-text" $ nf encodeToText (decodeA enA)
91+ , bench "aeson-to-text" $ nf encodeToText (decode enA)
103 , bench "json" $ nf encodeJ (decodeJ enJ)
92 , bench "json" $ nf encodeJ (decodeJ enJ)
104 ]
93 ]
105 , bgroup "jp" [
94 , bgroup "jp" [
106− bench "aeson-to-bytestring" $ nf A.encode (decodeA jpA)
95+ bench "aeson-to-bytestring" $ nf A.encode (decode jpA)
107− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA jpA)
96+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode jpA)
108− , bench "aeson-to-text" $ nf encodeToText (decodeA jpA)
97+ , bench "aeson-to-text" $ nf encodeToText (decode jpA)
109 , bench "json" $ nf encodeJ (decodeJ jpJ)
98 , bench "json" $ nf encodeJ (decodeJ jpJ)
110 ]
99 ]
111 ]
100 ]
benchmarks/Escape.hs+3−3
@@ -1,5 +1,5 @@
1−{-# LANGUAGE PackageImports #-}
2{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE ScopedTypeVariables #-}
2+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
3
3
4module Main (main) where
4module Main (main) where
5
5
@@ -7,8 +7,8 @@ import Prelude ()
7import Prelude.Compat
7import Prelude.Compat
8
8
9import Criterion.Main
9import Criterion.Main
10−import qualified "aeson-benchmarks" Data.Aeson.Parser.UnescapeFFI as FFI
10+import qualified Data.Aeson.Parser.UnescapeFFI as FFI
11−import qualified "aeson-benchmarks" Data.Aeson.Parser.UnescapePure as Pure
11+import qualified Data.Aeson.Parser.UnescapePure as Pure
12
12
13import qualified Data.ByteString.Char8 as BS
13import qualified Data.ByteString.Char8 as BS
14import System.Environment (getArgs, withArgs)
14import System.Environment (getArgs, withArgs)
benchmarks/Micro.hs+6−5
@@ -4,8 +4,9 @@ import Prelude ()
4import Prelude.Compat
4import Prelude.Compat
5
5
6import Criterion.Main
6import Criterion.Main
7−import qualified Data.Aeson.Encoding.Builder as AB
7+
8−import qualified Data.ByteString.Builder as B
8+-- Encoding is a newtype wrapper around Builder
9+import Data.Aeson.Encoding (text, string, encodingToLazyByteString)
9import qualified Data.Text as T
10import qualified Data.Text as T
10
11
11main :: IO ()
12main :: IO ()
@@ -13,8 +14,8 @@ main = do
13 let txt = "append (append b (primBounded w1 x1)) (primBounded w2 x2)"
14 let txt = "append (append b (primBounded w1 x1)) (primBounded w2 x2)"
14 defaultMain [
15 defaultMain [
15 bgroup "string" [
16 bgroup "string" [
16− bench "text" $ nf (B.toLazyByteString . AB.text) (T.pack txt)
17+ bench "text" $ nf (encodingToLazyByteString . text) (T.pack txt)
17− , bench "string direct" $ nf (B.toLazyByteString . AB.string) txt
18+ , bench "string direct" $ nf (encodingToLazyByteString . string) txt
18− , bench "string via text" $ nf (B.toLazyByteString . AB.text . T.pack) txt
19+ , bench "string via text" $ nf (encodingToLazyByteString . text . T.pack) txt
19 ]
20 ]
20 ]
21 ]
benchmarks/Typed/Common.hs−10
@@ -1,8 +1,3 @@
1−{-# LANGUAGE CPP #-}
2−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
3−{-# LANGUAGE PackageImports #-}
4−#endif
5−
6{-# OPTIONS_GHC -fno-warn-unused-imports #-}
1{-# OPTIONS_GHC -fno-warn-unused-imports #-}
7
2
8module Typed.Common (load) where
3module Typed.Common (load) where
@@ -14,12 +9,7 @@ import Data.ByteString.Lazy as L
14import System.Exit
9import System.Exit
15import System.IO
10import System.IO
16
11
17−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
18import Data.Aeson hiding (Result)
12import Data.Aeson hiding (Result)
19−#else
20−import "aeson" Data.Aeson hiding (Result)
21−import qualified "aeson-benchmarks" Data.Aeson as B
22−#endif
23
13
24load :: FromJSON a => FilePath -> IO a
14load :: FromJSON a => FilePath -> IO a
25load fileName = do
15load fileName = do
benchmarks/Typed/Generic.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
2module Typed.Generic (benchmarks, decodeBenchmarks) where
1module Typed.Generic (benchmarks, decodeBenchmarks) where
3
2
4import Prelude ()
3import Prelude ()
5import Prelude.Compat
4import Prelude.Compat
6
5
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
8import Criterion
7import Criterion
9import Data.ByteString.Lazy as L
8import Data.ByteString.Lazy as L
10import Twitter.Generic
9import Twitter.Generic
11import Typed.Common
10import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
13
11
14−encodeDirectA :: Result -> L.ByteString
12+encodeDirect :: Result -> L.ByteString
15−encodeDirectA = encode
13+encodeDirect = encode
16
14
17−encodeViaValueA :: Result -> L.ByteString
15+encodeViaValue :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
16+encodeViaValue = encode . toJSON
25
17
26benchmarks :: Benchmark
18benchmarks :: Benchmark
27benchmarks =
19benchmarks =
28 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
20 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29 bgroup "encodeGeneric" [
21 bgroup "encodeGeneric" [
30 bgroup "direct" [
22 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
23+ bench "twitter100" $ nf encodeDirect twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
24+ , bench "jp100" $ nf encodeDirect jp100
35 ]
25 ]
36 , bgroup "viaValue" [
26 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueB twitter100
27+ bench "twitter100" $ nf encodeViaValue twitter100
38− , bench "jp100" $ nf encodeViaValueB jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueA twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueA jp100
28+ , bench "jp100" $ nf encodeViaValue jp100
41 ]
29 ]
42 ]
30 ]
43
31
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
32+decodeDirect :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
33+decodeDirect = decode
49
34
50decodeBenchmarks :: Benchmark
35decodeBenchmarks :: Benchmark
51decodeBenchmarks =
36decodeBenchmarks =
52 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
37 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53 bgroup "decodeGeneric"
38 bgroup "decodeGeneric"
54 [ bgroup "direct"
39 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
41+ , bench "jp100" $ nf decodeDirect jp100
59 ]
42 ]
60 ]
43 ]
benchmarks/Typed/Manual.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
2module Typed.Manual (benchmarks, decodeBenchmarks) where
1module Typed.Manual (benchmarks, decodeBenchmarks) where
3
2
4import Prelude ()
3import Prelude ()
5import Prelude.Compat
4import Prelude.Compat
6
5
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
8import Criterion
7import Criterion
9import Data.ByteString.Lazy as L
8import Data.ByteString.Lazy as L
10import Twitter.Manual
9import Twitter.Manual
11import Typed.Common
10import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
13
11
14−encodeDirectA :: Result -> L.ByteString
12+encodeDirect :: Result -> L.ByteString
15−encodeDirectA = encode
13+encodeDirect = encode
16
14
17−encodeViaValueA :: Result -> L.ByteString
15+encodeViaValue :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
16+encodeViaValue = encode . toJSON
25
17
26benchmarks :: Benchmark
18benchmarks :: Benchmark
27benchmarks =
19benchmarks =
28 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
20 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29 bgroup "encodeManual" [
21 bgroup "encodeManual" [
30 bgroup "direct" [
22 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
23+ bench "twitter100" $ nf encodeDirect twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
24+ , bench "jp100" $ nf encodeDirect jp100
35 ]
25 ]
36 , bgroup "viaValue" [
26 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueB twitter100
27+ bench "twitter100" $ nf encodeViaValue twitter100
38− , bench "jp100" $ nf encodeViaValueB jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueA twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueA jp100
28+ , bench "jp100" $ nf encodeViaValue jp100
41 ]
29 ]
42 ]
30 ]
43
31
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
32+decodeDirect :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
33+decodeDirect = decode
49
34
50decodeBenchmarks :: Benchmark
35decodeBenchmarks :: Benchmark
51decodeBenchmarks =
36decodeBenchmarks =
52 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
37 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53 bgroup "decodeManual"
38 bgroup "decodeManual"
54 [ bgroup "direct"
39 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
41+ , bench "jp100" $ nf decodeDirect jp100
59 ]
42 ]
60 ]
43 ]
benchmarks/Typed/TH.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
2module Typed.TH (benchmarks, decodeBenchmarks) where
1module Typed.TH (benchmarks, decodeBenchmarks) where
3
2
4import Prelude ()
3import Prelude ()
5import Prelude.Compat
4import Prelude.Compat
6
5
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
8import Criterion
7import Criterion
9import Data.ByteString.Lazy as L
8import Data.ByteString.Lazy as L
10import Twitter.TH
9import Twitter.TH
11import Typed.Common
10import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
13
11
14−encodeDirectA :: Result -> L.ByteString
12+encodeDirect :: Result -> L.ByteString
15−encodeDirectA = encode
13+encodeDirect = encode
16
14
17−encodeViaValueA :: Result -> L.ByteString
15+encodeViaValue :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
16+encodeViaValue = encode . toJSON
25
17
26benchmarks :: Benchmark
18benchmarks :: Benchmark
27benchmarks =
19benchmarks =
28 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
20 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29 bgroup "encodeTH" [
21 bgroup "encodeTH" [
30 bgroup "direct" [
22 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
23+ bench "twitter100" $ nf encodeDirect twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
24+ , bench "jp100" $ nf encodeDirect jp100
35 ]
25 ]
36 , bgroup "viaValue" [
26 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueA twitter100
27+ bench "twitter100" $ nf encodeViaValue twitter100
38− , bench "jp100" $ nf encodeViaValueA jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueB twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueB jp100
28+ , bench "jp100" $ nf encodeViaValue jp100
41 ]
29 ]
42 ]
30 ]
43
31
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
32+decodeDirect :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
33+decodeDirect = decode
49
34
50decodeBenchmarks :: Benchmark
35decodeBenchmarks :: Benchmark
51decodeBenchmarks =
36decodeBenchmarks =
52 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
37 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53 bgroup "decodeTH"
38 bgroup "decodeTH"
54 [ bgroup "direct"
39 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
41+ , bench "jp100" $ nf decodeDirect jp100
59 ]
42 ]
60 ]
43 ]
benchmarks/aeson-benchmarks.cabal+99−76
@@ -8,59 +8,14 @@ flag bytestring-builder
8 default: False
8 default: False
9 manual: False
9 manual: False
10
10
11+flag local-aeson
12+ description: Build the local version of aeson, to avoid rebuilding aeson's
13+ reverse dependencies for benchmarking (statistics, criterion).
14+ default: True
15+ manual: True
16+
11library
17library
12 default-language: Haskell2010
18 default-language: Haskell2010
13− hs-source-dirs: .. . ../ffi ../pure ../attoparsec-iso8601
14− c-sources: ../cbits/unescape_string.c
15− exposed-modules:
16− Data.Aeson
17− Data.Aeson.Compat
18− Data.Aeson.Encoding
19− Data.Aeson.Encoding.Builder
20− Data.Aeson.Encoding.Internal
21− Data.Aeson.Internal
22− Data.Aeson.Internal.Functions
23− Data.Aeson.Internal.Time
24− Data.Aeson.Parser
25− Data.Aeson.Parser.Internal
26− Data.Aeson.Parser.Time
27− Data.Aeson.Parser.Unescape
28− Data.Aeson.Parser.UnescapeFFI
29− Data.Aeson.Parser.UnescapePure
30− Data.Aeson.TH
31− Data.Aeson.Text
32− Data.Aeson.Types
33− Data.Aeson.Types.Class
34− Data.Aeson.Types.FromJSON
35− Data.Aeson.Types.Generic
36− Data.Aeson.Types.Internal
37− Data.Aeson.Types.ToJSON
38− Data.Attoparsec.Time
39− Data.Attoparsec.Time.Internal
40−
41− build-depends:
42− attoparsec >= 0.13.0.1,
43− base == 4.*,
44− base-compat >= 0.9.1 && <0.10,
45− time-locale-compat >=0.1.1 && <0.2,
46− containers,
47− deepseq,
48− dlist >= 0.2,
49− fail == 4.9.*,
50− ghc-prim >= 0.2,
51− hashable >= 1.1.2.0,
52− mtl,
53− scientific >= 0.3.4.7 && < 0.4,
54− syb,
55− tagged >=0.8.3 && <0.9,
56− template-haskell >= 2.4,
57− text >= 1.1.1.0,
58− th-abstraction >= 0.2.2 && < 0.3,
59− time,
60− transformers,
61− unordered-containers >= 0.2.3.0,
62− uuid-types >= 1.0.3 && <1.1,
63− vector >= 0.7.1
64
19
65 if flag(bytestring-builder)
20 if flag(bytestring-builder)
66 build-depends: bytestring >= 0.9 && < 0.10.4,
21 build-depends: bytestring >= 0.9 && < 0.10.4,
@@ -68,32 +23,106 @@ library
68 else
23 else
69 build-depends: bytestring >= 0.10.4
24 build-depends: bytestring >= 0.10.4
70
25
71− if impl(ghc >=7.8)
26+ if flag(local-aeson)
72− cpp-options: -DHAS_COERCIBLE
27+
28+ hs-source-dirs: .. ../ffi ../pure ../attoparsec-iso8601
29+ c-sources: ../cbits/unescape_string.c
30+ build-depends:
31+ attoparsec >= 0.13.0.1,
32+ base == 4.*,
33+ base-compat >= 0.9.1 && <0.10,
34+ time-locale-compat >=0.1.1 && <0.2,
35+ containers,
36+ deepseq,
37+ dlist >= 0.2,
38+ fail == 4.9.*,
39+ ghc-prim >= 0.2,
40+ hashable >= 1.1.2.0,
41+ mtl,
42+ scientific >= 0.3.4.7 && < 0.4,
43+ syb,
44+ tagged >=0.8.3 && <0.9,
45+ template-haskell >= 2.4,
46+ text >= 1.1.1.0,
47+ th-abstraction >= 0.2.2 && < 0.3,
48+ time,
49+ transformers,
50+ unordered-containers >= 0.2.3.0,
51+ uuid-types >= 1.0.3 && <1.1,
52+ vector >= 0.7.1
73
53
74− if !impl(ghc >= 8.0)
54+ if !impl(ghc >= 7.10)
75− -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
55+ -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
76− build-depends: semigroups >= 0.18.2 && < 0.19
56+ build-depends: nats >= 1 && < 1.2
77
57
58+ if impl(ghc >=7.8)
59+ cpp-options: -DHAS_COERCIBLE
60+
61+ if !impl(ghc >= 8.0)
62+ -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
63+ build-depends: semigroups >= 0.18.2 && < 0.19
64+
78− include-dirs: ../include
65+ include-dirs: ../include
66+
67+ ghc-options: -O2 -Wall
68+ cpp-options: -DGENERICS
69+
70+ exposed-modules:
71+ Data.Aeson
72+ Data.Aeson.Compat
73+ Data.Aeson.Encoding
74+ Data.Aeson.Encoding.Builder
75+ Data.Aeson.Encoding.Internal
76+ Data.Aeson.Internal
77+ Data.Aeson.Internal.Functions
78+ Data.Aeson.Internal.Time
79+ Data.Aeson.Parser
80+ Data.Aeson.Parser.Internal
81+ Data.Aeson.Parser.Time
82+ Data.Aeson.Parser.Unescape
83+ Data.Aeson.Parser.UnescapeFFI
84+ Data.Aeson.Parser.UnescapePure
85+ Data.Aeson.TH
86+ Data.Aeson.Text
87+ Data.Aeson.Types
88+ Data.Aeson.Types.Class
89+ Data.Aeson.Types.FromJSON
90+ Data.Aeson.Types.Generic
91+ Data.Aeson.Types.Internal
92+ Data.Aeson.Types.ToJSON
93+ Data.Attoparsec.Time
94+ Data.Attoparsec.Time.Internal
95+
96+ else
79
97
80− ghc-options: -O2 -Wall
98+ build-depends: aeson
81− cpp-options: -DGENERICS
99+
100+ reexported-modules:
101+ Data.Aeson,
102+ Data.Aeson.Encoding,
103+ Data.Aeson.Parser.Internal,
104+ Data.Aeson.Text,
105+ Data.Aeson.TH,
106+ Data.Aeson.Types
82
107
83executable aeson-benchmark-escape
108executable aeson-benchmark-escape
84 default-language: Haskell2010
109 default-language: Haskell2010
85 main-is: Escape.hs
110 main-is: Escape.hs
86 hs-source-dirs: ../examples .
111 hs-source-dirs: ../examples .
87 ghc-options: -Wall -O2 -rtsopts
112 ghc-options: -Wall -O2 -rtsopts
113+ if flag(local-aeson)
88− build-depends:
114+ build-depends:
89− aeson-benchmarks,
115+ aeson-benchmarks,
90− base,
116+ base,
91− base-compat,
117+ base-compat,
92− bytestring,
118+ bytestring,
93− criterion >= 1.0,
119+ criterion >= 1.0,
94− deepseq,
120+ deepseq,
95− ghc-prim,
121+ ghc-prim,
96− text
122+ text
123+ else
124+ -- Disabled because of inaccessible internals
125+ buildable: False
97
126
98executable aeson-benchmark-compare
127executable aeson-benchmark-compare
99 default-language: Haskell2010
128 default-language: Haskell2010
@@ -139,9 +168,6 @@ executable aeson-benchmark-typed
139 main-is: Typed.hs
168 main-is: Typed.hs
140 hs-source-dirs: ../examples .
169 hs-source-dirs: ../examples .
141 ghc-options: -Wall -O2 -rtsopts
170 ghc-options: -Wall -O2 -rtsopts
142− -- We must help ourself in situations when there is both
143− -- aeson and aeson-benchmakrs
144− cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
145 other-modules:
171 other-modules:
146 Twitter
172 Twitter
147 Twitter.Generic
173 Twitter.Generic
@@ -153,7 +179,6 @@ executable aeson-benchmark-typed
153 Typed.Manual
179 Typed.Manual
154 Typed.TH
180 Typed.TH
155 build-depends:
181 build-depends:
156− aeson,
157 aeson-benchmarks,
182 aeson-benchmarks,
158 base,
183 base,
159 base-compat,
184 base-compat,
@@ -173,9 +198,7 @@ executable aeson-benchmark-compare-with-json
173 default-language: Haskell2010
198 default-language: Haskell2010
174 main-is: CompareWithJSON.hs
199 main-is: CompareWithJSON.hs
175 ghc-options: -Wall -O2 -rtsopts
200 ghc-options: -Wall -O2 -rtsopts
176− cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
177 build-depends:
201 build-depends:
178− aeson,
179 aeson-benchmarks,
202 aeson-benchmarks,
180 base,
203 base,
181 base-compat,
204 base-compat,
@@ -235,13 +258,14 @@ executable aeson-benchmark-dates
235 aeson-benchmarks,
258 aeson-benchmarks,
236 text,
259 text,
237 time
260 time
261+ if impl(ghc >= 8.2)
262+ ghc-options: -Wno-simplifiable-class-constraints
238
263
239executable aeson-benchmark-map
264executable aeson-benchmark-map
240 default-language: Haskell2010
265 default-language: Haskell2010
241 main-is: AesonMap.hs
266 main-is: AesonMap.hs
242 ghc-options: -Wall -O2 -rtsopts
267 ghc-options: -Wall -O2 -rtsopts
243 build-depends:
268 build-depends:
244− aeson,
245 aeson-benchmarks,
269 aeson-benchmarks,
246 base,
270 base,
247 base-compat,
271 base-compat,
@@ -259,7 +283,6 @@ executable aeson-benchmark-foldable
259 main-is: AesonFoldable.hs
283 main-is: AesonFoldable.hs
260 ghc-options: -Wall -O2 -rtsopts
284 ghc-options: -Wall -O2 -rtsopts
261 build-depends:
285 build-depends:
262− aeson,
263 aeson-benchmarks,
286 aeson-benchmarks,
264 base,
287 base,
265 base-compat,
288 base-compat,
examples/Twitter/Generic.hs−36
@@ -1,12 +1,7 @@
1-- Use GHC generics to automatically generate good instances.
1-- Use GHC generics to automatically generate good instances.
2
2
3−{-# LANGUAGE CPP #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
5
4
6−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
7−{-# LANGUAGE PackageImports #-}
8−#endif
9−
10module Twitter.Generic
5module Twitter.Generic
11 (
6 (
12 Metadata(..)
7 Metadata(..)
@@ -21,12 +16,7 @@ import Prelude.Compat ()
21import Twitter
16import Twitter
22import Twitter.Options
17import Twitter.Options
23
18
24−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
25import Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
19import Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
26−#else
27−import "aeson" Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
28−import qualified "aeson-benchmarks" Data.Aeson as B
29−#endif
30
20
31instance ToJSON Metadata where
21instance ToJSON Metadata where
32 toJSON = genericToJSON twitterOptions
22 toJSON = genericToJSON twitterOptions
@@ -51,29 +41,3 @@ instance ToJSON Result where
51 toEncoding = genericToEncoding twitterOptions
41 toEncoding = genericToEncoding twitterOptions
52instance FromJSON Result where
42instance FromJSON Result where
53 parseJSON = genericParseJSON twitterOptions
43 parseJSON = genericParseJSON twitterOptions
54−
55−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
56−instance B.ToJSON Metadata where
57− toJSON = B.genericToJSON btwitterOptions
58− toEncoding = B.genericToEncoding btwitterOptions
59−instance B.FromJSON Metadata where
60− parseJSON = B.genericParseJSON btwitterOptions
61−
62−instance B.ToJSON Geo where
63− toJSON = B.genericToJSON btwitterOptions
64− toEncoding = B.genericToEncoding btwitterOptions
65−instance B.FromJSON Geo where
66− parseJSON = B.genericParseJSON btwitterOptions
67−
68−instance B.ToJSON Story where
69− toJSON = B.genericToJSON btwitterOptions
70− toEncoding = B.genericToEncoding btwitterOptions
71−instance B.FromJSON Story where
72− parseJSON = B.genericParseJSON btwitterOptions
73−
74−instance B.ToJSON Result where
75− toJSON = B.genericToJSON btwitterOptions
76− toEncoding = B.genericToEncoding btwitterOptions
77−instance B.FromJSON Result where
78− parseJSON = B.genericParseJSON btwitterOptions
79−#endif
examples/Twitter/Manual.hs−135
@@ -1,14 +1,9 @@
1-- Manually write instances.
1-- Manually write instances.
2
2
3−{-# LANGUAGE CPP #-}
4{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE RecordWildCards #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
7
6
8−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
9−{-# LANGUAGE PackageImports #-}
10−#endif
11−
12module Twitter.Manual
7module Twitter.Manual
13 (
8 (
14 Metadata(..)
9 Metadata(..)
@@ -25,12 +20,7 @@ import Data.Monoid ((<>))
25import Prelude hiding (id)
20import Prelude hiding (id)
26import Twitter
21import Twitter
27
22
28−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
29import Data.Aeson hiding (Result)
23import Data.Aeson hiding (Result)
30−#else
31−import "aeson" Data.Aeson hiding (Result)
32−import qualified "aeson-benchmarks" Data.Aeson as B
33−#endif
34
24
35instance ToJSON Metadata where
25instance ToJSON Metadata where
36
26
@@ -155,128 +145,3 @@ instance FromJSON Result where
155 <*> v .: "max_id_str"
145 <*> v .: "max_id_str"
156 <*> v .: "query"
146 <*> v .: "query"
157 parseJSON _ = empty
147 parseJSON _ = empty
158−
159−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
160−instance B.ToJSON Metadata where
161− toJSON Metadata{..} = B.object [
162− "result_type" B..= result_type
163− ]
164−
165− toEncoding Metadata{..} = B.pairs $
166− "result_type" B..= result_type
167−
168−instance B.FromJSON Metadata where
169− parseJSON (B.Object v) = Metadata <$> v B..: "result_type"
170− parseJSON _ = empty
171−
172−instance B.ToJSON Geo where
173− toJSON Geo{..} = B.object [
174− "type_" B..= type_
175− , "coordinates" B..= coordinates
176− ]
177−
178− toEncoding Geo{..} = B.pairs $
179− "type_" B..= type_
180− <> "coordinates" B..= coordinates
181−
182−instance B.FromJSON Geo where
183− parseJSON (B.Object v) = Geo <$>
184− v B..: "type_"
185− <*> v B..: "coordinates"
186− parseJSON _ = empty
187−
188−instance B.ToJSON Story where
189− toJSON Story{..} = B.object [
190− "from_user_id_str" B..= from_user_id_str
191− , "profile_image_url" B..= profile_image_url
192− , "created_at" B..= created_at
193− , "from_user" B..= from_user
194− , "id_str" B..= id_str
195− , "metadata" B..= metadata
196− , "to_user_id" B..= to_user_id
197− , "text" B..= text
198− , "id" B..= id_
199− , "from_user_id" B..= from_user_id
200− , "geo" B..= geo
201− , "iso_language_code" B..= iso_language_code
202− , "to_user_id_str" B..= to_user_id_str
203− , "source" B..= source
204− ]
205−
206− toEncoding Story{..} = B.pairs $
207− "from_user_id_str" B..= from_user_id_str
208− <> "profile_image_url" B..= profile_image_url
209− <> "created_at" B..= created_at
210− <> "from_user" B..= from_user
211− <> "id_str" B..= id_str
212− <> "metadata" B..= metadata
213− <> "to_user_id" B..= to_user_id
214− <> "text" B..= text
215− <> "id" B..= id_
216− <> "from_user_id" B..= from_user_id
217− <> "geo" B..= geo
218− <> "iso_language_code" B..= iso_language_code
219− <> "to_user_id_str" B..= to_user_id_str
220− <> "source" B..= source
221−
222−instance B.FromJSON Story where
223− parseJSON (B.Object v) = Story <$>
224− v B..: "from_user_id_str"
225− <*> v B..: "profile_image_url"
226− <*> v B..: "created_at"
227− <*> v B..: "from_user"
228− <*> v B..: "id_str"
229− <*> v B..: "metadata"
230− <*> v B..: "to_user_id"
231− <*> v B..: "text"
232− <*> v B..: "id"
233− <*> v B..: "from_user_id"
234− <*> v B..: "geo"
235− <*> v B..: "iso_language_code"
236− <*> v B..: "to_user_id_str"
237− <*> v B..: "source"
238− parseJSON _ = empty
239−
240−instance B.ToJSON Result where
241− toJSON Result{..} = B.object [
242− "results" B..= results
243− , "max_id" B..= max_id
244− , "since_id" B..= since_id
245− , "refresh_url" B..= refresh_url
246− , "next_page" B..= next_page
247− , "results_per_page" B..= results_per_page
248− , "page" B..= page
249− , "completed_in" B..= completed_in
250− , "since_id_str" B..= since_id_str
251− , "max_id_str" B..= max_id_str
252− , "query" B..= query
253− ]
254−
255− toEncoding Result{..} = B.pairs $
256− "results" B..= results
257− <> "max_id" B..= max_id
258− <> "since_id" B..= since_id
259− <> "refresh_url" B..= refresh_url
260− <> "next_page" B..= next_page
261− <> "results_per_page" B..= results_per_page
262− <> "page" B..= page
263− <> "completed_in" B..= completed_in
264− <> "since_id_str" B..= since_id_str
265− <> "max_id_str" B..= max_id_str
266− <> "query" B..= query
267−
268−instance B.FromJSON Result where
269− parseJSON (B.Object v) = Result <$>
270− v B..: "results"
271− <*> v B..: "max_id"
272− <*> v B..: "since_id"
273− <*> v B..: "refresh_url"
274− <*> v B..: "next_page"
275− <*> v B..: "results_per_page"
276− <*> v B..: "page"
277− <*> v B..: "completed_in"
278− <*> v B..: "since_id_str"
279− <*> v B..: "max_id_str"
280− <*> v B..: "query"
281− parseJSON _ = empty
282−#endif
examples/Twitter/Options.hs−21
@@ -1,18 +1,6 @@
1−{-# LANGUAGE CPP #-}
2−
3−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
4−{-# LANGUAGE PackageImports #-}
5−#endif
6−
7module Twitter.Options (module Twitter.Options) where
1module Twitter.Options (module Twitter.Options) where
8
2
9−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
10import Data.Aeson
3import Data.Aeson
11−import Data.Aeson.Types
12−#else
13−import "aeson" Data.Aeson
14−import qualified "aeson-benchmarks" Data.Aeson as B
15−#endif
16
4
17twitterOptions :: Options
5twitterOptions :: Options
18twitterOptions = defaultOptions
6twitterOptions = defaultOptions
@@ -20,12 +8,3 @@ twitterOptions = defaultOptions
20 "id_" -> "id"
8 "id_" -> "id"
21 _ -> x
9 _ -> x
22 }
10 }
23−
24−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
25−btwitterOptions :: B.Options
26−btwitterOptions = B.defaultOptions
27− { B.fieldLabelModifier = \x -> case x of
28− "id_" -> "id"
29− _ -> x
30− }
31−#endif
examples/Twitter/TH.hs−17
@@ -1,13 +1,8 @@
1-- Use Template Haskell to generate good instances.
1-- Use Template Haskell to generate good instances.
2
2
3−{-# LANGUAGE CPP #-}
4{-# LANGUAGE TemplateHaskell #-}
3{-# LANGUAGE TemplateHaskell #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
6
5
7−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
8−{-# LANGUAGE PackageImports #-}
9−#endif
10−
11module Twitter.TH
6module Twitter.TH
12 (
7 (
13 Metadata(..)
8 Metadata(..)
@@ -21,21 +16,9 @@ import Prelude ()
21import Twitter
16import Twitter
22import Twitter.Options
17import Twitter.Options
23
18
24−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
25import Data.Aeson.TH
19import Data.Aeson.TH
26−#else
27−import "aeson" Data.Aeson.TH
28−import qualified "aeson-benchmarks" Data.Aeson.TH as B
29−#endif
30
20
31$(deriveJSON twitterOptions ''Metadata)
21$(deriveJSON twitterOptions ''Metadata)
32$(deriveJSON twitterOptions ''Geo)
22$(deriveJSON twitterOptions ''Geo)
33$(deriveJSON twitterOptions ''Story)
23$(deriveJSON twitterOptions ''Story)
34$(deriveJSON twitterOptions ''Result)
24$(deriveJSON twitterOptions ''Result)
35−
36−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
37−$(B.deriveJSON btwitterOptions ''Metadata)
38−$(B.deriveJSON btwitterOptions ''Geo)
39−$(B.deriveJSON btwitterOptions ''Story)
40−$(B.deriveJSON btwitterOptions ''Result)
41−#endif