on master help sign in
Merge pull request #563 from phadej/benchmarks-fix-562

Benchmarks fix #562

commit6306cec8b8b33d4d76b3c8d7e476b6b91d81e2c3 authorAdam Bergmark <adam@bergmark.nl> dateFri 14 Jul 2017, 18:32 (9 years ago) parent2bc6f22ad4bb7b
13 files changed+227−49
.gitignore+1 benchmarks/AesonMap.hs+6−6 benchmarks/CompareWithJSON.hs+32−7 benchmarks/Dates.hs+1 benchmarks/Typed.hs+3 benchmarks/Typed/Generic.hs+21−3 benchmarks/Typed/Manual.hs+20−2 benchmarks/Typed/TH.hs+20−2 benchmarks/aeson-benchmarks.cabal+19 examples/Twitter/Generic.hs+49−19 examples/Twitter/Options.hs+33 examples/Twitter/TH.hs+13−9 stack-bench.yaml+9−1
.gitignore+1
@@ -4,6 +4,7 @@ dist-newstyle
44.cabal-sandbox/
55cabal.sandbox.config
66.stack-work/
7+.stack-work-bench/
78
89*.o
910*.hi
benchmarks/AesonMap.hs+6−6
@@ -160,7 +160,7 @@ benchDecodeHM name val = bgroup name
160160 , bench "Identity" $ nf (decodeHMB proxyT1) val
161161 , bench "Coerce" $ nf (decodeHMB proxyT2) val
162162 , bench "Parser" $ nf (decodeHMB proxyT3) val
163− , bench "aeson-0.11" $ nf (decodeHMA proxyText) val
163+ , bench "aeson-hackage" $ nf (decodeHMA proxyText) val
164164 , bench "Tagged Text" $ nf (decodeHMB $ proxyTagged proxyText) val
165165 , bench "Tagged Identity" $ nf (decodeHMB $ proxyTagged proxyT1) val
166166 , bench "Tagged Coerce" $ nf (decodeHMB $ proxyTagged proxyT2) val
@@ -172,11 +172,11 @@ benchDecodeMap
172172 -> LBS.ByteString
173173 -> Benchmark
174174benchDecodeMap name val = bgroup name
175− [ bench "Text" $ nf (decodeMapB proxyText) val
176− , bench "Identity" $ nf (decodeMapB proxyT1) val
177− , bench "Coerce" $ nf (decodeMapB proxyT2) val
178− , bench "Parser" $ nf (decodeMapB proxyT3) val
179− , bench "aeson-0.11" $ nf (decodeMapA proxyText) val
175+ [ bench "Text" $ nf (decodeMapB proxyText) val
176+ , bench "Identity" $ nf (decodeMapB proxyT1) val
177+ , bench "Coerce" $ nf (decodeMapB proxyT2) val
178+ , bench "Parser" $ nf (decodeMapB proxyT3) val
179+ , bench "aeson-hackage" $ nf (decodeMapA proxyText) val
180180 ]
181181
182182benchEncodeHM
benchmarks/CompareWithJSON.hs+32−7
@@ -1,3 +1,4 @@
1+{-# LANGUAGE PackageImports #-}
12{-# OPTIONS_GHC -fno-warn-orphans #-}
23
34module Main (main) where
@@ -10,8 +11,11 @@ import Blaze.ByteString.Builder.Char.Utf8 (fromString)
1011import Control.DeepSeq (NFData(rnf))
1112import Criterion.Main
1213import Data.Maybe (fromMaybe)
13−import qualified Data.Aeson as A
14−import qualified Data.Aeson.Text as A
14+import qualified "aeson-benchmarks" Data.Aeson as A
15+import qualified "aeson-benchmarks" Data.Aeson.Text as A
16+import qualified "aeson-benchmarks" Data.Aeson.Parser.Internal as I
17+import qualified "aeson" Data.Aeson as B
18+import qualified Data.ByteString as BS
1519import qualified Data.ByteString.Lazy as BL
1620import qualified Data.Text.Lazy as TL
1721import qualified Data.Text.Lazy.Builder as TLB
@@ -41,6 +45,19 @@ decodeA s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
4145decodeA' :: BL.ByteString -> A.Value
4246decodeA' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
4347
48+decodeAS :: BS.ByteString -> A.Value
49+decodeAS 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+
57+decodeIP :: BL.ByteString -> A.Value
58+decodeIP s = fromMaybe (error "fail to parse via Parser.decodeWith") $
59+ I.decodeWith I.jsonEOF A.fromJSON s
60+
4461encodeJ :: J.JSValue -> BL.ByteString
4562encodeJ = toLazyByteString . fromString . J.encode
4663
@@ -55,19 +72,27 @@ main = do
5572 let enFile = "json-data/twitter100.json"
5673 jpFile = "json-data/jp100.json"
5774 enA <- BL.readFile enFile
75+ enS <- BS.readFile enFile
5876 enJ <- readFile enFile
5977 jpA <- BL.readFile jpFile
78+ jpS <- BS.readFile jpFile
6079 jpJ <- readFile jpFile
6180 defaultMain [
6281 bgroup "decode" [
6382 bgroup "en" [
64− bench "aeson/lazy" $ nf decodeA enA
65− , bench "aeson/strict" $ nf decodeA' enA
66− , bench "json" $ nf decodeJ enJ
83+ bench "aeson/lazy" $ nf decodeA enA
84+ , bench "aeson/strict" $ nf decodeA' enA
85+ , bench "aeson/stricter" $ nf decodeAS enS
86+ , bench "aeson/hackage" $ nf decodeB enA
87+ , bench "aeson/hackage'" $ nf decodeBS enS
88+ , bench "aeson/parser" $ nf decodeIP enA
89+ , bench "json" $ nf decodeJ enJ
6790 ]
6891 , bgroup "jp" [
69− bench "aeson" $ nf decodeA jpA
70− , bench "json" $ nf decodeJ jpJ
92+ bench "aeson" $ nf decodeA jpA
93+ , bench "aeson/stricter" $ nf decodeAS jpS
94+ , bench "aeson/hackage" $ nf decodeB jpA
95+ , bench "json" $ nf decodeJ jpJ
7196 ]
7297 ]
7398 , bgroup "encode" [
benchmarks/Dates.hs+1
@@ -1,3 +1,4 @@
1+{-# OPTIONS_GHC -fsimpl-tick-factor=0 #-}
12module Main (main) where
23
34import Prelude ()
benchmarks/Typed.hs+3
@@ -13,4 +13,7 @@ main = defaultMain [
1313 Generic.benchmarks
1414 , Manual.benchmarks
1515 , TH.benchmarks
16+ , Generic.decodeBenchmarks
17+ , Manual.decodeBenchmarks
18+ , TH.decodeBenchmarks
1619 ]
benchmarks/Typed/Generic.hs+21−3
@@ -1,5 +1,5 @@
11{-# LANGUAGE PackageImports #-}
2−module Typed.Generic (benchmarks) where
2+module Typed.Generic (benchmarks, decodeBenchmarks) where
33
44import Prelude ()
55import Prelude.Compat
@@ -7,7 +7,7 @@ import Prelude.Compat
77import "aeson" Data.Aeson hiding (Result)
88import Criterion
99import Data.ByteString.Lazy as L
10−import Twitter.TH
10+import Twitter.Generic
1111import Typed.Common
1212import qualified "aeson-benchmarks" Data.Aeson as B
1313
@@ -26,7 +26,7 @@ encodeViaValueB = B.encode . B.toJSON
2626benchmarks :: Benchmark
2727benchmarks =
2828 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29− bgroup "generic" [
29+ bgroup "encodeGeneric" [
3030 bgroup "direct" [
3131 bench "twitter100" $ nf encodeDirectB twitter100
3232 , bench "jp100" $ nf encodeDirectB jp100
@@ -40,3 +40,21 @@ benchmarks =
4040 , bench "jp100 baseline" $ nf encodeViaValueA jp100
4141 ]
4242 ]
43+
44+decodeDirectA :: L.ByteString -> Maybe Result
45+decodeDirectA = decode
46+
47+decodeDirectB :: L.ByteString -> Maybe Result
48+decodeDirectB = B.decode
49+
50+decodeBenchmarks :: Benchmark
51+decodeBenchmarks =
52+ env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53+ bgroup "decodeGeneric"
54+ [ bgroup "direct"
55+ [ bench "twitter100" $ nf decodeDirectB twitter100
56+ , bench "jp100" $ nf decodeDirectB jp100
57+ , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58+ , bench "jp100 baseline" $ nf decodeDirectA jp100
59+ ]
60+ ]
benchmarks/Typed/Manual.hs+20−2
@@ -1,5 +1,5 @@
11{-# LANGUAGE PackageImports #-}
2−module Typed.Manual (benchmarks) where
2+module Typed.Manual (benchmarks, decodeBenchmarks) where
33
44import Prelude ()
55import Prelude.Compat
@@ -26,7 +26,7 @@ encodeViaValueB = B.encode . B.toJSON
2626benchmarks :: Benchmark
2727benchmarks =
2828 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29− bgroup "manual" [
29+ bgroup "encodeManual" [
3030 bgroup "direct" [
3131 bench "twitter100" $ nf encodeDirectB twitter100
3232 , bench "jp100" $ nf encodeDirectB jp100
@@ -40,3 +40,21 @@ benchmarks =
4040 , bench "jp100 baseline" $ nf encodeViaValueA jp100
4141 ]
4242 ]
43+
44+decodeDirectA :: L.ByteString -> Maybe Result
45+decodeDirectA = decode
46+
47+decodeDirectB :: L.ByteString -> Maybe Result
48+decodeDirectB = B.decode
49+
50+decodeBenchmarks :: Benchmark
51+decodeBenchmarks =
52+ env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53+ bgroup "decodeManual"
54+ [ bgroup "direct"
55+ [ bench "twitter100" $ nf decodeDirectB twitter100
56+ , bench "jp100" $ nf decodeDirectB jp100
57+ , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58+ , bench "jp100 baseline" $ nf decodeDirectA jp100
59+ ]
60+ ]
benchmarks/Typed/TH.hs+20−2
@@ -1,5 +1,5 @@
11{-# LANGUAGE PackageImports #-}
2−module Typed.TH (benchmarks) where
2+module Typed.TH (benchmarks, decodeBenchmarks) where
33
44import Prelude ()
55import Prelude.Compat
@@ -26,7 +26,7 @@ encodeViaValueB = B.encode . B.toJSON
2626benchmarks :: Benchmark
2727benchmarks =
2828 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
29− bgroup "th" [
29+ bgroup "encodeTH" [
3030 bgroup "direct" [
3131 bench "twitter100" $ nf encodeDirectB twitter100
3232 , bench "jp100" $ nf encodeDirectB jp100
@@ -40,3 +40,21 @@ benchmarks =
4040 , bench "jp100 baseline" $ nf encodeViaValueB jp100
4141 ]
4242 ]
43+
44+decodeDirectA :: L.ByteString -> Maybe Result
45+decodeDirectA = decode
46+
47+decodeDirectB :: L.ByteString -> Maybe Result
48+decodeDirectB = B.decode
49+
50+decodeBenchmarks :: Benchmark
51+decodeBenchmarks =
52+ env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
53+ bgroup "decodeTH"
54+ [ bgroup "direct"
55+ [ bench "twitter100" $ nf decodeDirectB twitter100
56+ , bench "jp100" $ nf decodeDirectB jp100
57+ , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58+ , bench "jp100 baseline" $ nf decodeDirectA jp100
59+ ]
60+ ]
benchmarks/aeson-benchmarks.cabal+19
@@ -83,6 +83,13 @@ executable aeson-benchmark-compare
8383 main-is: Compare.hs
8484 hs-source-dirs: ../examples .
8585 ghc-options: -Wall -O2 -rtsopts
86+ other-modules:
87+ Compare.BufferBuilder
88+ Compare.JsonBench
89+ Compare.JsonBuilder
90+ Twitter
91+ Twitter.Manual
92+ Typed.Common
8693 build-depends:
8794 aeson-benchmarks,
8895 base,
@@ -116,6 +123,16 @@ executable aeson-benchmark-typed
116123 -- We must help ourself in situations when there is both
117124 -- aeson and aeson-benchmakrs
118125 cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
126+ other-modules:
127+ Twitter
128+ Twitter.Generic
129+ Twitter.Manual
130+ Twitter.Options
131+ Twitter.TH
132+ Typed.Common
133+ Typed.Generic
134+ Typed.Manual
135+ Typed.TH
119136 build-depends:
120137 aeson,
121138 aeson-benchmarks,
@@ -136,7 +153,9 @@ executable aeson-benchmark-typed
136153executable aeson-benchmark-compare-with-json
137154 main-is: CompareWithJSON.hs
138155 ghc-options: -Wall -O2 -rtsopts
156+ cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
139157 build-depends:
158+ aeson,
140159 aeson-benchmarks,
141160 base,
142161 base-compat,
examples/Twitter/Generic.hs+49−19
@@ -1,7 +1,12 @@
11-- Use GHC generics to automatically generate good instances.
2+
23{-# LANGUAGE CPP #-}
34{-# OPTIONS_GHC -fno-warn-orphans #-}
45
6+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
7+{-# LANGUAGE PackageImports #-}
8+#endif
9+
510module Twitter.Generic
611 (
712 Metadata(..)
@@ -11,39 +16,64 @@ module Twitter.Generic
1116 ) where
1217
1318import Prelude ()
14−import Prelude.Compat
19+import Prelude.Compat ()
1520
1621import Twitter
22+import Twitter.Options
1723
1824#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
19−import Data.Aeson (ToJSON, FromJSON)
25+import Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
2026#else
21−import "aeson" Data.Aeson (ToJSON, FromJSON)
27+import "aeson" Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
2228import qualified "aeson-benchmarks" Data.Aeson as B
2329#endif
2430
25−instance ToJSON Metadata
26−instance FromJSON Metadata
31+instance ToJSON Metadata where
32+ toJSON = genericToJSON twitterOptions
33+ toEncoding = genericToEncoding twitterOptions
34+instance FromJSON Metadata where
35+ parseJSON = genericParseJSON twitterOptions
2736
28−instance ToJSON Geo
29−instance FromJSON Geo
37+instance ToJSON Geo where
38+ toJSON = genericToJSON twitterOptions
39+ toEncoding = genericToEncoding twitterOptions
40+instance FromJSON Geo where
41+ parseJSON = genericParseJSON twitterOptions
3042
31−instance ToJSON Story
32−instance FromJSON Story
43+instance ToJSON Story where
44+ toJSON = genericToJSON twitterOptions
45+ toEncoding = genericToEncoding twitterOptions
46+instance FromJSON Story where
47+ parseJSON = genericParseJSON twitterOptions
3348
34−instance ToJSON Result
35−instance FromJSON Result
49+instance ToJSON Result where
50+ toJSON = genericToJSON twitterOptions
51+ toEncoding = genericToEncoding twitterOptions
52+instance FromJSON Result where
53+ parseJSON = genericParseJSON twitterOptions
3654
3755#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
38−instance B.ToJSON Metadata
39−instance B.FromJSON Metadata
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
4061
41−instance B.ToJSON Geo
42−instance B.FromJSON Geo
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
4367
44−instance B.ToJSON Story
45−instance B.FromJSON Story
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
4673
47−instance B.ToJSON Result
48−instance B.FromJSON Result
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
4979#endif
examples/Twitter/Options.hsnew file+33
@@ -0,0 +1,33 @@
1+{-# LANGUAGE CPP #-}
2+
3+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
4+{-# LANGUAGE PackageImports #-}
5+#endif
6+
7+module Twitter.Options (module Twitter.Options) where
8+
9+#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
10+import Data.Aeson
11+import Data.Aeson.Types
12+#else
13+import "aeson" Data.Aeson
14+import "aeson" Data.Aeson.Types
15+import qualified "aeson-benchmarks" Data.Aeson as B
16+import qualified "aeson-benchmarks" Data.Aeson.Types as B
17+#endif
18+
19+twitterOptions :: Options
20+twitterOptions = defaultOptions
21+ { fieldLabelModifier = \x -> case x of
22+ "id_" -> "id"
23+ _ -> x
24+ }
25+
26+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
27+btwitterOptions :: B.Options
28+btwitterOptions = B.defaultOptions
29+ { B.fieldLabelModifier = \x -> case x of
30+ "id_" -> "id"
31+ _ -> x
32+ }
33+#endif
examples/Twitter/TH.hs+13−9
@@ -1,10 +1,13 @@
11-- Use Template Haskell to generate good instances.
22
33{-# LANGUAGE CPP #-}
4−{-# LANGUAGE PackageImports #-}
54{-# LANGUAGE TemplateHaskell #-}
65{-# OPTIONS_GHC -fno-warn-orphans #-}
76
7+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
8+{-# LANGUAGE PackageImports #-}
9+#endif
10+
811module Twitter.TH
912 (
1013 Metadata(..)
@@ -16,6 +19,7 @@ module Twitter.TH
1619import Prelude ()
1720
1821import Twitter
22+import Twitter.Options
1923
2024#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
2125import Data.Aeson.TH
@@ -24,14 +28,14 @@ import "aeson" Data.Aeson.TH
2428import qualified "aeson-benchmarks" Data.Aeson.TH as B
2529#endif
2630
27−$(deriveJSON defaultOptions ''Metadata)
28−$(deriveJSON defaultOptions ''Geo)
29−$(deriveJSON defaultOptions ''Story)
30−$(deriveJSON defaultOptions ''Result)
31+$(deriveJSON twitterOptions ''Metadata)
32+$(deriveJSON twitterOptions ''Geo)
33+$(deriveJSON twitterOptions ''Story)
34+$(deriveJSON twitterOptions ''Result)
3135
3236#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
33−$(B.deriveJSON B.defaultOptions ''Metadata)
34−$(B.deriveJSON B.defaultOptions ''Geo)
35−$(B.deriveJSON B.defaultOptions ''Story)
36−$(B.deriveJSON B.defaultOptions ''Result)
37+$(B.deriveJSON btwitterOptions ''Metadata)
38+$(B.deriveJSON btwitterOptions ''Geo)
39+$(B.deriveJSON btwitterOptions ''Story)
40+$(B.deriveJSON btwitterOptions ''Result)
3741#endif
stack-bench.yaml+9−1
@@ -1,7 +1,15 @@
11resolver: lts-8.5
2+# We use aeson in the snapshot to
3+# - avoid recompilation of criterion
4+# - compare against it
5+# - '.'
6+#
7+# Also we use separate working directory to avoid "unregistering aeson"
8+# caused recompilations
9+work-dir: .stack-work-bench
210packages:
3−- '.'
411- benchmarks
512extra-deps:
13+- aeson-1.2.1.0
614- quickcheck-instances-0.3.14
715- th-abstraction-0.2.2.0