Implement Data.Text.unpack and Data.Text.toTitle directly, without streaming - #611
Conversation
|
I might be benchmarking this incorrectly, but I think it has a negative impact on performance. Main.hsmodule Main (main) where
import Criterion.Main
import Data.Text.Internal (Text(..))
import Data.Text.Unsafe (Iter(..), iterArray)
import Data.Text qualified as T
unpack :: Text -> String
unpack (Text arr off len) = go 0
where
go !i
| i >= len = []
| otherwise = c : go (i + l)
where
Iter c l = iterArray arr (off+i)
{-# INLINE [1] unpack #-}
f1 :: String -> String
f1 = T.unpack . T.toTitle . T.pack
{-# NOINLINE f1 #-}
f2 :: String -> String
f2 = unpack . T.toTitle . T.pack
{-# NOINLINE f2 #-}
testInput :: String
testInput = "this is a pretty short string, all things considered."
testInputT :: Text
testInputT = T.pack testInput
{-# NOINLINE testInputT #-}
main :: IO ()
main = defaultMain
[ bgroup "fusion"
[ bench "old" $ nf f1 testInput
, bench "new" $ nf f2 testInput
]
, bgroup "just unpack"
[ bench "old" $ nf T.unpack testInputT
, bench "new" $ nf unpack testInputT
]
] |
a1eba87 to
d289882
Compare
|
Thanks @rhendric, should be fixed now. |
|
My comment wasn't about f1 :: String -> String
f1 = T.unpack . T.scanl max '\0' . T.pack
{-# NOINLINE f1 #-}
f2 :: String -> String
f2 = unpack . T.scanl max '\0' . T.pack
{-# NOINLINE f2 #-} |
|
@rhendric we are gradually rewriting all stream-based functions to their non-streaming counterparts. E. g., see |
|
Ah, okay then! |
Data.Text.unpack and Data.Text.toTitle directly, without streaming
Related to our discussion with @rhendric at https://discourse.haskell.org/t/the-quest-to-completely-eradicate-string-awkwardness/10111/75?u=bodigrim, let's implement
Data.Text.unpackdirectly viaiterArrayinstead of streaming / unstreaming. My immediate goal is to simplify dependencies between modules oftext, but I imagine that performance could get better as well.