on master help sign in
Measure and improve replicate.

--HG-- extra : convert_revision : ddb5ec18fd00c45ab6b446bda87b3ffb317e2d35

commitcc1b015dd3892856d531daf1582f9dd68d95c400 authorBryan O'Sullivan <bos@serpentine.com> dateWed 2 Dec 2009, 08:05 (17 years ago) parent187893f
4 files changed+52−15
Data/Text.hs+16−6 Data/Text/Fusion/Common.hs+7−5 Data/Text/Lazy.hs+4−4 tests/Benchmarks.hs+25
Data/Text.hs+16−6
@@ -164,8 +164,8 @@ module Data.Text
164164import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
165165 Eq(..), Ord(..), (++),
166166 Read(..), Show(..),
167− (&&), (||), (+), (-), (.), ($), (>>),
168− fromIntegral, div, not, return, otherwise)
167+ (&&), (||), (+), (-), (.), ($), (>>), (*),
168+ div, not, return, otherwise)
169169import Control.DeepSeq (NFData)
170170import Control.Exception (assert)
171171import Data.Char (isSpace)
@@ -666,11 +666,21 @@ mapAccumR f s t = case uncons t of
666666-- ** Generating and unfolding 'Text's
667667
668668-- | /O(n*m)/ 'replicate' @n@ @t@ is a 'Text' consisting of the input
669−-- @t@ repeated @n@ times. Subject to fusion.
669+-- @t@ repeated @n@ times.
670670replicate :: Int -> Text -> Text
671−replicate n t
672− | isSingleton t = replicateChar n (unsafeHead t)
673− | otherwise = unstream (S.replicateI (fromIntegral n) (S.stream t))
671+replicate n t@(Text a o l)
672+ | n <= 0 || l <= 0 = empty
673+ | n == 1 = t
674+ | isSingleton t = replicateChar n (unsafeHead t)
675+ | otherwise = Text (A.run x) 0 len
676+ where
677+ len = l * n
678+ x = do
679+ arr <- A.unsafeNew len
680+ let loop !d !i | i >= n = return arr
681+ | otherwise = let m = d + l
682+ in copy arr d a o m >> loop m (i+1)
683+ loop 0 0
674684{-# INLINE [1] replicate #-}
675685
676686{-# RULES
Data/Text/Fusion/Common.hs+7−5
@@ -601,16 +601,18 @@ replicateCharI n c
601601 | otherwise = Yield c (i + 1)
602602{-# INLINE [0] replicateCharI #-}
603603
604+data RI s = RI !s {-# UNPACK #-} !Int64
605+
604606replicateI :: Int64 -> Stream Char -> Stream Char
605607replicateI n (Stream next0 s0 len) =
606− Stream next (0 :*: s0) (fromIntegral (max 0 n) * len)
608+ Stream next (RI s0 0) (fromIntegral (max 0 n) * len)
607609 where
608− next (k :*: s)
610+ next (RI s k)
609611 | k >= n = Done
610612 | otherwise = case next0 s of
611− Done -> Skip (k+1 :*: s0)
612− Skip s' -> Skip (k :*: s')
613− Yield x s' -> Yield x (k :*: s')
613+ Done -> Skip (RI s0 (k+1))
614+ Skip s' -> Skip (RI s' k)
615+ Yield x s' -> Yield x (RI s' k)
614616{-# INLINE [0] replicateI #-}
615617
616618-- | /O(n)/, where @n@ is the length of the result. The unfoldr function
Data/Text/Lazy.hs+4−4
@@ -644,11 +644,11 @@ mapAccumR f s t = case uncons t of
644644 (s', ys) = mapAccumR f s xs
645645
646646-- | /O(n*m)/ 'replicate' @n@ @t@ is a 'Text' consisting of the input
647−-- @t@ repeated @n@ times. Subject to fusion.
647+-- @t@ repeated @n@ times.
648648replicate :: Int64 -> Text -> Text
649−replicate n t
650− | isSingleton t = replicateChar n (head t)
651− | otherwise = unstream (S.replicateI n (S.stream t))
649+replicate n t = concat (rep 0)
650+ where rep i | i >= n = []
651+ | otherwise = t : rep (i+1)
652652{-# INLINE replicate #-}
653653
654654-- | /O(n)/ 'replicateChar' @n@ @c@ is a 'Text' of length @n@ with @c@ the
tests/Benchmarks.hs+25
@@ -190,6 +190,18 @@ main = do
190190 , bench "bl" $ nf (BL.map f . BL.map f) bla
191191 , bench "l" $ nf (L.map f . L.map f) la
192192 ],
193+ bgroup "replicate" [
194+ bench "ts" $ nf (TS.replicate bsa_len) (TS.singleton c)
195+ , bench "tl" $ nf (TL.replicate (fromIntegral bsa_len)) (TL.singleton c)
196+ , bench "bs" $ nf (BS.replicate bsa_len) c
197+ , bench "bl" $ nf (BL.replicate (fromIntegral bsa_len)) c
198+ , bench "l" $ nf (L.replicate bsa_len) c
199+ ],
200+ bgroup "2replicate" [
201+ bench "ts" $ nf (TS.replicate (bsa_len `div` TS.length tsw)) tsw
202+ , bench "tl" $ nf (TL.replicate (fromIntegral bsa_len `div` TL.length tlw)) tlw
203+ , bench "l" $ nf (replicat (bsa_len `div` TS.length tsw)) lw
204+ ],
193205 bgroup "reverse" [
194206 bench "ts" $ nf TS.reverse tsa
195207 , bench "tl" $ nf TL.reverse tla
@@ -295,6 +307,18 @@ main = do
295307 , bench "bs" $ nf (BS.length . BS.map f . BS.map f) bsa
296308 , bench "l" $ nf (L.length . L.map f . L.map f) la
297309 ],
310+ bgroup "replicate" [
311+ bench "ts" $ nf (TS.length . TS.replicate bsa_len) (TS.singleton c)
312+ , bench "tl" $ nf (TL.length . TL.replicate (fromIntegral bsa_len)) (TL.singleton c)
313+ , bench "bs" $ nf (BS.length . BS.replicate bsa_len) c
314+ , bench "bl" $ nf (BL.length . BL.replicate (fromIntegral bsa_len)) c
315+ , bench "l" $ nf (L.length . L.replicate bsa_len) c
316+ ],
317+ bgroup "2replicate" [
318+ bench "ts" $ nf (TS.length . TS.replicate (bsa_len `div` TS.length tsw)) tsw
319+ , bench "tl" $ nf (TL.length . TL.replicate (fromIntegral bsa_len `div` TL.length tlw)) tlw
320+ , bench "l" $ nf (L.length . replicat (bsa_len `div` TS.length tsw)) lw
321+ ],
298322 bgroup "take" [
299323 bench "ts" $ nf (TS.length . TS.take (tsa_len `div` 3)) tsa
300324 , bench "tl" $ nf (TL.length . TL.take (tla_len `div` 3)) tla
@@ -336,6 +360,7 @@ main = do
336360 tlw = TL.fromChunks [tsw]
337361 f (C# c#) = C# (chr# (ord# c# +# 1#))
338362 len l _ = l + (1::Int)
363+ replicat n = concat . L.replicate n
339364
340365chunksOf :: Int -> BS.ByteString -> [BS.ByteString]
341366chunksOf k = go