From 1a6a06ad8cbef42628dabc099c987c2af55a1756 Mon Sep 17 00:00:00 2001 From: meooow25 Date: Thu, 11 Jan 2024 20:14:18 +0530 Subject: [PATCH] Optimize the implementation of Data.Text.concat Avoid allocating intermediate lists. The algorithm used is not changed, the total length is calculated in one pass over the input and the output Text populated in another pass. Note: In case there is one non-empty Text and one or more empty Texts, the non-empty Text is copied whereas it would previously be returned as is. The behavior is unchanged for every other case. --- src/Data/Text.hs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Data/Text.hs b/src/Data/Text.hs index 72c1b96d..2ee2e7d3 100644 --- a/src/Data/Text.hs +++ b/src/Data/Text.hs @@ -1033,18 +1033,18 @@ foldr' f z t = S.foldl' (P.flip f) z (reverseStream t) -- | /O(n)/ Concatenate a list of 'Text's. concat :: [Text] -> Text -concat ts = case ts' of - [] -> empty - [t] -> t - _ -> Text (A.run go) 0 len +concat ts = case ts of + [] -> empty + [t] -> t + _ | len == 0 -> empty + | otherwise -> Text (A.run go) 0 len where - ts' = L.filter (not . null) ts - len = sumP "concat" $ L.map lengthWord8 ts' + len = sumP "concat" $ L.map lengthWord8 ts go :: ST s (A.MArray s) go = do arr <- A.new len let step i (Text a o l) = A.copyI l arr i a o >> return (i + l) - foldM step 0 ts' >> return arr + foldM step 0 ts >> return arr -- | /O(n)/ Map a function over a 'Text' that results in a 'Text', and -- concatenate the results. @@ -2015,12 +2015,12 @@ stripSuffix p@(Text _arr _off plen) t@(Text arr off len) -- | Add a list of non-negative numbers. Errors out on overflow. sumP :: String -> [Int] -> Int -sumP fun = go 0 - where go !a (x:xs) - | ax >= 0 = go ax xs +sumP fun = L.foldl' add 0 + where add a x + | ax >= 0 = ax | otherwise = overflowError fun where ax = a + x - go a _ = a +{-# INLINE sumP #-} -- Use foldl' and inline for fusion. emptyError :: HasCallStack => String -> a emptyError fun = P.error $ "Data.Text." ++ fun ++ ": empty input"