DPutils-0.0.2.0: tests/streaming.hs
-- | Test the performance of splitting and consuming a *very long* bytestring
-- using @streaming@.
module Main where
import Data.Functor.Of
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy.Char8 as BSL8
import qualified Data.ByteString.Streaming.Char8 as SB8
import System.TimeIt
import Text.Printf
import qualified Data.ByteString.Streaming.Split as SBS
genLong
∷ ( Monad m )
⇒ Int
→ SB8.ByteString m ()
genLong = SB8.fromLazy . BSL8.fromChunks . go
where
-- create chunks of strict char8 bytestring to concatenate.
go !k
| k <= 0 = []
| otherwise = chunk : go (k-1)
-- the chunk to use for concatenation.
!chunk = BS8.pack $ ['A'..'Z'] ++ "\n" ++ ['a'..'z']
{-# Inlinable genLong #-}
-- | Generate long strings, split them after every 10 characters (which is
-- different from the chunk length), concatenate the resulting strings, and get
-- the total string length.
--
-- This function should run in constant memory.
longLength ∷ ( Monad m ) ⇒ Int → m (Of Int ())
longLength = SB8.length . SB8.concat . SBS.splitsByteStringAt 10 . genLong
otherLength ∷ ( Monad m ) ⇒ Int → m (Of Int ())
otherLength = SB8.length . SB8.concat . SBS.separatesByteString (SB8.splitAt 10) . genLong
benchmark ∷ (Int → IO (Of Int ())) → Int → Int → IO ()
benchmark !f !k !l = do
(!seconds, !n :> ()) ← timeItT $ f l
printf "53 * 10^%2d = %10d characters in %9.6f seconds\n" k n seconds
main = do
putStrLn "longLength"
mapM_ (uncurry (benchmark longLength)) [(k ∷ Int, 10^k) | k ← [0..7]]
putStrLn "otherLength"
mapM_ (uncurry (benchmark otherLength)) [(k ∷ Int, 10^k) | k ← [0..7]]
return ()