22-- Copyright: (c) 2022 Andrew Lelechenko
33-- Licence: BSD3
44-- Maintainer: Andrew Lelechenko <[email protected] > 5+
56module BenchDecimal (benchDecimal ) where
67
7- import Data.ByteString qualified as B
8- import Data.ByteString.Builder qualified as B
9- import Data.Text qualified as T
10- import Data.Text.Builder.Linear.Buffer ( Buffer , runBuffer , ($$<|) , ($<|) , (|>$) , (|>$$) )
8+ import qualified Data.ByteString as B
9+ import qualified Data.ByteString.Builder as B
10+ import qualified Data.Text as T
11+ import Data.Text.Builder.Linear.Buffer
1112import Data.Text.Lazy (toStrict )
1213import Data.Text.Lazy.Builder (toLazyText )
1314import Data.Text.Lazy.Builder.Int (decimal )
14- import Test.Tasty.Bench ( Benchmark , bench , bgroup , nf )
15+ import Test.Tasty.Bench
1516
1617#ifdef MIN_VERSION_text_builder
1718import qualified TextBuilder
@@ -21,125 +22,56 @@ import qualified TextBuilder
2122import qualified ByteString.StrictBuilder
2223#endif
2324
24- benchDecimal ∷ Benchmark
25- benchDecimal = bgroup " Decimal" [benchBoundedDecimal, benchUnboundedDecimal]
26-
27- --------------------------------------------------------------------------------
28- -- Bounded
29- --------------------------------------------------------------------------------
30-
31- int ∷ Int
25+ int :: Int
3226int = 123456789123456789
3327
34- benchLazyBuilder ∷ Integral a ⇒ a → Int → T. Text
35- benchLazyBuilder k = toStrict . toLazyText . go mempty
28+ benchLazyBuilder ∷ Int → T. Text
29+ benchLazyBuilder = toStrict . toLazyText . go mempty
3630 where
3731 go ! acc 0 = acc
38- go ! acc n = let i = fromIntegral n * k in go (decimal i <> (acc <> decimal i)) (n - 1 )
39- {-# SPECIALIZE benchLazyBuilder ∷ Int → Int → T.Text #-}
40- {-# SPECIALIZE benchLazyBuilder ∷ Integer → Int → T.Text #-}
32+ go ! acc n = let i = n * int in go (decimal i <> (acc <> decimal i)) (n - 1 )
4133
42- benchLazyBuilderBS ∷ Int → Int → B. ByteString
43- benchLazyBuilderBS k = B. toStrict . B. toLazyByteString . go mempty
34+ benchLazyBuilderBS ∷ Int → B. ByteString
35+ benchLazyBuilderBS = B. toStrict . B. toLazyByteString . go mempty
4436 where
4537 go ! acc 0 = acc
46- go ! acc n = let i = n * k in go (B. intDec i <> (acc <> B. intDec i)) (n - 1 )
38+ go ! acc n = let i = n * int in go (B. intDec i <> (acc <> B. intDec i)) (n - 1 )
4739
4840#ifdef MIN_VERSION_text_builder
49- benchStrictBuilder ∷ ( Integral a ) ⇒ a → Int → T. Text
50- benchStrictBuilder k = TextBuilder. toText . go mempty
41+ benchStrictBuilder ∷ Int → T. Text
42+ benchStrictBuilder = TextBuilder. toText . go mempty
5143 where
5244 go ! acc 0 = acc
53- go ! acc n = let i = fromIntegral n * k in go (TextBuilder. decimal i <> (acc <> TextBuilder. decimal i)) (n - 1 )
54- {-# SPECIALIZE benchStrictBuilder ∷ Int → Int → T.Text #-}
55- {-# SPECIALIZE benchStrictBuilder ∷ Integer → Int → T.Text #-}
45+ go ! acc n = let i = n * int in go (TextBuilder. decimal i <> (acc <> TextBuilder. decimal i)) (n - 1 )
5646#endif
5747
5848#ifdef MIN_VERSION_bytestring_strict_builder
59- benchStrictBuilderBS ∷ ( Integral a ) ⇒ a → Int → B. ByteString
60- benchStrictBuilderBS k = ByteString.StrictBuilder. builderBytes . go mempty
49+ benchStrictBuilderBS ∷ Int → B. ByteString
50+ benchStrictBuilderBS = ByteString.StrictBuilder. builderBytes . go mempty
6151 where
6252 go ! acc 0 = acc
63- go ! acc n = let i = fromIntegral n * k in go (ByteString.StrictBuilder. asciiIntegral i <> (acc <> ByteString.StrictBuilder. asciiIntegral i)) (n - 1 )
64- {-# SPECIALIZE benchStrictBuilderBS ∷ Int → Int → B.ByteString #-}
65- {-# SPECIALIZE benchStrictBuilderBS ∷ Integer → Int → B.ByteString #-}
53+ go ! acc n = let i = n * int in go (ByteString.StrictBuilder. asciiIntegral i <> (acc <> ByteString.StrictBuilder. asciiIntegral i)) (n - 1 )
6654#endif
6755
68- benchBoundedLinearBuilder ∷ Int → Int → T. Text
69- benchBoundedLinearBuilder k m = runBuffer (\ b → go b m)
56+ benchLinearBuilder ∷ Int → T. Text
57+ benchLinearBuilder m = runBuffer (\ b → go b m)
7058 where
7159 go ∷ Buffer ⊸ Int → Buffer
7260 go ! acc 0 = acc
73- go ! acc n = let i = n * k in go (i $<| (acc |>$ i)) (n - 1 )
74-
75- benchBoundedDecimal ∷ Benchmark
76- benchBoundedDecimal = bgroup " Bounded" $ map mkBoundedGroup [1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 , 1e6 ]
77-
78- mkBoundedGroup ∷ Int → Benchmark
79- mkBoundedGroup n =
80- bgroup
81- (show n)
82- [ bench " Data.Text.Lazy.Builder" $ nf (benchLazyBuilder int) n
83- , bench " Data.ByteString.Builder" $ nf (benchLazyBuilderBS int) n
84- #ifdef MIN_VERSION_text_builder
85- , bench " TextBuilder" $ nf (benchStrictBuilder int) n
86- #endif
87- #ifdef MIN_VERSION_bytestring_strict_builder
88- , bench " ByteString.StrictBuilder" $ nf (benchStrictBuilderBS int) n
89- #endif
90- , bench " Data.Text.Builder.Linear" $ nf (benchBoundedLinearBuilder int) n
91- ]
92-
93- --------------------------------------------------------------------------------
94- -- Unbounded
95- --------------------------------------------------------------------------------
96-
97- integerSmall ∷ Integer
98- integerSmall = toInteger (div @ Word maxBound 20 )
61+ go ! acc n = let i = n * int in go (i $<| (acc |>$ i)) (n - 1 )
9962
100- integerBig ∷ Integer
101- integerBig = toInteger (maxBound @ Word - 1 ) ^ (10 ∷ Word )
102-
103- integerHuge ∷ Integer
104- integerHuge = toInteger (maxBound @ Word - 1 ) ^ (100 ∷ Word )
105-
106- benchUnboundedDecimal ∷ Benchmark
107- benchUnboundedDecimal =
108- bgroup
109- " Unbounded"
110- [ bgroup " Small" $ map (mkUnboundedGroup integerSmall) [1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 ]
111- , bgroup " Big" $ map (mkUnboundedGroup integerBig) [1e0 , 1e1 , 1e2 , 1e3 , 1e4 ]
112- , bgroup " Huge" $ map (mkUnboundedGroup integerHuge) [1e0 , 1e1 , 1e2 , 1e3 ]
113- ]
114-
115- -- NOTE: In the following benchmarks, the ByteString builder would share work
116- -- if the prepender and the appender are identical, while our linear buffer does
117- -- not. So we increment the appender to get a fair benchmark.
118-
119- benchUnboundedLazyBuilderBS ∷ Integer → Int → B. ByteString
120- benchUnboundedLazyBuilderBS k = B. toStrict . B. toLazyByteString . go mempty
121- where
122- go ! acc 0 = acc
123- go ! acc n = let i = fromIntegral n * k in go (B. integerDec i <> (acc <> B. integerDec (i + 1 ))) (n - 1 )
124-
125- benchUnboundedLinearBuilder ∷ Integer → Int → T. Text
126- benchUnboundedLinearBuilder k m = runBuffer (\ b → go b m)
127- where
128- go ∷ Buffer ⊸ Int → Buffer
129- go ! acc 0 = acc
130- go ! acc n = let i = fromIntegral n * k in go (i $$<| (acc |>$$ (i + 1 ))) (n - 1 )
63+ benchDecimal ∷ Benchmark
64+ benchDecimal = bgroup " Decimal" $ map mkGroup [1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 , 1e6 ]
13165
132- mkUnboundedGroup ∷ Integer → Int → Benchmark
133- mkUnboundedGroup integer n =
134- bgroup
135- (show n)
136- [ bench " Data.Text.Lazy.Builder" $ nf (benchLazyBuilder integer) n
137- , bench " Data.ByteString.Builder" $ nf (benchUnboundedLazyBuilderBS integer) n
66+ mkGroup :: Int → Benchmark
67+ mkGroup n = bgroup (show n)
68+ [ bench " Data.Text.Lazy.Builder" $ nf benchLazyBuilder n
69+ , bench " Data.ByteString.Builder" $ nf benchLazyBuilderBS n
13870#ifdef MIN_VERSION_text_builder
139- , bench " TextBuilder" $ nf ( benchStrictBuilder integer) n
71+ , bench " TextBuilder" $ nf benchStrictBuilder n
14072#endif
14173#ifdef MIN_VERSION_bytestring_strict_builder
142- , bench " ByteString.StrictBuilder" $ nf ( benchStrictBuilderBS integer) n
74+ , bench " ByteString.StrictBuilder" $ nf benchStrictBuilderBS n
14375#endif
144- , bench " Data.Text.Builder. Linear" $ nf (benchUnboundedLinearBuilder integer) n
145- ]
76+ , bench " Data.TextBuilder. Linear" $ nf benchLinearBuilder n
77+ ]
0 commit comments