on master help sign in
Added RULES to merge adjacent bounds checks.

This speeds up the "builder/mappend 8 char" benchmark by 39%. The number of merged bounds checks is currently limited to -fmax-simplifier-iterations. Replacing 'append' (and perhaps 'writeN') with some other combinator might fix that problem. --HG-- extra : convert_revision : 544680871090133b873457b13c531de66bd91e30

commita4bd0288cda7073509df49329c1f03d7b605913c authorJohan Tibell <johan.tibell@gmail.com> dateWed 12 May 2010, 11:36 (16 years ago) parentda5b829
2 files changed+30−3
Data/Text/Lazy/Builder.hs+21−3 tests/Benchmarks.hs+9
Data/Text/Lazy/Builder.hs+21−3
@@ -97,7 +97,7 @@ singleton c = putChar c
9797--
9898append :: Builder -> Builder -> Builder
9999append (Builder f) (Builder g) = Builder (f . g)
100−{-# INLINE append #-}
100+{-# INLINE [1] append #-}
101101
102102-- TODO: Experiment to find the right threshold.
103103copyLimit :: Int
@@ -201,13 +201,13 @@ ensureFree !n = withSize $ \ l ->
201201 if n <= l
202202 then empty
203203 else flush `append` withBuffer (const (newBuffer (max n defaultChunkSize)))
204−{-# INLINE ensureFree #-}
204+{-# INLINE [1] ensureFree #-}
205205
206206-- | Ensure that @n@ many elements are available, and then use @f@ to
207207-- write some elements into the memory.
208208writeN :: Int -> (forall s. A.MArray s Word16 -> Int -> ST s ()) -> Builder
209209writeN n f = ensureFree 1 `append` withBuffer (writeNBuffer n f)
210−{-# INLINE writeN #-}
210+{-# INLINE [1] writeN #-}
211211
212212writeNBuffer :: Int -> (A.MArray s Word16 -> Int -> ST s ()) -> (Buffer s)
213213 -> ST s (Buffer s)
@@ -235,3 +235,21 @@ unsafeCopy src sidx dest didx count =
235235 | otherwise = do A.unsafeWrite dest j (A.unsafeIndex src i)
236236 copy_loop (i+1) (j+1) (c+1)
237237{-# INLINE unsafeCopy #-}
238+
239+------------------------------------------------------------------------
240+-- Some nice rules for Builder
241+
242+{-# RULES
243+
244+"writeN/combine" forall a b (f::forall s. A.MArray s Word16 -> Int -> ST s ())
245+ (g::forall s. A.MArray s Word16 -> Int -> ST s ()).
246+ append (writeN a f) (writeN b g) =
247+ (writeN (a+b) (\marr o -> f marr o >> g marr (o+a)))
248+
249+"ensureFree/combine" forall a b .
250+ append (ensureFree a) (ensureFree b) = ensureFree (max a b)
251+
252+"flush/combine"
253+ append flush flush = flush
254+
255+ #-}
tests/Benchmarks.hs+9
@@ -393,6 +393,7 @@ main = do
393393 ],
394394 bgroup "builder" [
395395 bench "mappend char" $ nf (TL.length . TB.toLazyText . mappendNChar 'a') 10000,
396+ bench "mappend 8 char" $ nf (TL.length . TB.toLazyText . mappend8Char) 'a',
396397 bench "mappend text" $ nf (TL.length . TB.toLazyText . mappendNText short) 10000
397398 ]
398399 ]
@@ -424,6 +425,14 @@ mappendNChar c n = go 0 mempty
424425 | i < n = go (i+1) (acc `mappend` TB.singleton c)
425426 | otherwise = acc
426427
428+-- Gives more opportunity for inlining and elimination of unnecesary
429+-- bounds checks.
430+mappend8Char :: Char -> TB.Builder
431+mappend8Char c = TB.singleton c `mappend` TB.singleton c `mappend`
432+ TB.singleton c `mappend` TB.singleton c `mappend`
433+ TB.singleton c `mappend` TB.singleton c `mappend`
434+ TB.singleton c `mappend` TB.singleton c
435+
427436mappendNText :: TS.Text -> Int -> TB.Builder
428437mappendNText t n = go 0 mempty
429438 where