1{-# OPTIONS_GHC -Wno-deprecations #-}
4-- Module : Stream.Split
5-- Copyright : (c) 2019 Composewell Technologies
6-- License : BSD-3-Clause
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
12{-# LANGUAGE ScopedTypeVariables #-}
14#ifdef __HADDOCK_VERSION__
19{-# LANGUAGE TemplateHaskell #-}
20{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
23module Stream.Split (benchmarks) where
26import Data.Word (Word8)
27import System.IO (Handle)
29import qualified Streamly.FileSystem.Handle as FH
30import qualified Streamly.Internal.Data.Array as A
31import qualified Streamly.Internal.Data.Fold as FL
32import qualified Streamly.Internal.Data.Parser as PR
33import qualified Streamly.Internal.Data.Stream.IsStream as IP
34import qualified Streamly.Internal.FileSystem.Handle as IFH
35import qualified Streamly.Internal.Unicode.Stream as IUS
36import qualified Streamly.Prelude as S
38import Gauge hiding (env)
39import Prelude hiding (last, length)
40import Streamly.Benchmark.Common
41import Streamly.Benchmark.Common.Handle
44import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
46import qualified Streamly.Internal.Data.Array.Mut.Type as MA
47import qualified Streamly.Internal.Data.Unfold as IUF
52 -------------------------------------------------------------------------------
53-- reduce with splitting transformations
54-------------------------------------------------------------------------------
57lf = fromIntegral (ord '\n')
59toarr :: String -> A.Array Word8
60toarr = A.fromList . map (fromIntegral . ord)
62-- | Split on line feed.
63splitOn :: Handle -> IO Int
65 (S.length $ S.splitOn (== lf) FL.drain
66 $ S.unfold FH.read inh) -- >>= print
69inspect $ hasNoTypeClasses 'splitOn
70inspect $ 'splitOn `hasNoType` ''Step
71inspect $ 'splitOn `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
72inspect $ 'splitOn `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
75-- | Split suffix on line feed.
76splitOnSuffix :: Handle -> IO Int
78 (S.length $ S.splitOnSuffix (== lf) FL.drain
79 $ S.unfold FH.read inh) -- >>= print
82inspect $ hasNoTypeClasses 'splitOnSuffix
83inspect $ 'splitOnSuffix `hasNoType` ''Step
84inspect $ 'splitOnSuffix `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
85inspect $ 'splitOnSuffix `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
88-- | Split suffix with line feed.
89splitWithSuffix :: Handle -> IO Int
91 (S.length $ S.splitWithSuffix (== lf) FL.drain
92 $ S.unfold FH.read inh) -- >>= print
95inspect $ hasNoTypeClasses 'splitWithSuffix
96inspect $ 'splitWithSuffix `hasNoType` ''Step
97inspect $ 'splitWithSuffix `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
98inspect $ 'splitWithSuffix `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
101-- | Split on line feed.
102foldManySepBy :: Handle -> IO Int
106 (FL.takeEndBy_ (== lf) FL.drain)
107 (S.unfold FH.read inh)
110-- | Split on line feed.
111parseManySepBy :: Handle -> IO Int
115 (PR.fromFold $ FL.takeEndBy_ (== lf) FL.drain)
116 (S.unfold FH.read inh)
120wordsBy :: Handle -> IO Int
122 (S.length $ S.wordsBy isSp FL.drain
123 $ S.unfold FH.read inh) -- >>= print
126inspect $ hasNoTypeClasses 'wordsBy
127inspect $ 'wordsBy `hasNoType` ''Step
128inspect $ 'wordsBy `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
129inspect $ 'wordsBy `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
132-- | Split on a word8 sequence.
133splitOnSeq :: String -> Handle -> IO Int
135 (S.length $ IP.splitOnSeq (toarr str) FL.drain
136 $ S.unfold FH.read inh) -- >>= print
139-- inspect $ hasNoTypeClasses 'splitOnSeq
140-- inspect $ 'splitOnSeq `hasNoType` ''Step
143-- | Split on a word8 sequence.
144splitOnSeq100k :: Handle -> IO Int
145splitOnSeq100k inh = do
146 arr <- A.fromStream $ S.replicate 100000 123
147 (S.length $ IP.splitOnSeq arr FL.drain
148 $ S.unfold FH.read inh) -- >>= print
150-- | Split on suffix sequence.
151splitOnSuffixSeq :: String -> Handle -> IO Int
152splitOnSuffixSeq str inh =
153 (S.length $ IP.splitOnSuffixSeq (toarr str) FL.drain
154 $ S.unfold FH.read inh) -- >>= print
157-- inspect $ hasNoTypeClasses 'splitOnSuffixSeq
158-- inspect $ 'splitOnSuffixSeq `hasNoType` ''Step
161-- | Split on suffix sequence.
162splitWithSuffixSeq :: String -> Handle -> IO Int
163splitWithSuffixSeq str inh =
164 S.length $ IP.splitWithSuffixSeq (toarr str) FL.drain
165 $ S.unfold FH.read inh -- >>= print
167o_1_space_reduce_read_split :: BenchEnv -> [Benchmark]
168o_1_space_reduce_read_split env =
170 [ mkBench "S.foldMany (FL.takeEndBy_ (== lf) FL.drain)" env
171 $ \inh _ -> foldManySepBy inh
172 , mkBench "S.parseMany (FL.takeEndBy_ (== lf) FL.drain)" env
173 $ \inh _ -> parseManySepBy inh
174 , mkBench "S.wordsBy isSpace FL.drain" env $ \inh _ ->
176 , mkBench "S.splitOn (== lf) FL.drain" env $ \inh _ ->
178 , mkBench "S.splitOnSuffix (== lf) FL.drain" env $ \inh _ ->
180 , mkBench "S.splitWithSuffix (== lf) FL.drain" env $ \inh _ ->
182 , mkBench "S.splitOnSeq \"\" FL.drain" env $ \inh _ ->
184 , mkBench "S.splitOnSuffixSeq \"\" FL.drain" env $ \inh _ ->
185 splitOnSuffixSeq "" inh
186 , mkBench "S.splitOnSeq \"\\n\" FL.drain" env $ \inh _ ->
188 , mkBench "S.splitOnSuffixSeq \"\\n\" FL.drain" env $ \inh _ ->
189 splitOnSuffixSeq "\n" inh
190 , mkBench "S.splitOnSeq \"a\" FL.drain" env $ \inh _ ->
192 , mkBench "S.splitOnSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
193 splitOnSeq "\r\n" inh
194 , mkBench "S.splitOnSuffixSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
195 splitOnSuffixSeq "\r\n" inh
196 , mkBench "S.splitWithSuffixSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
197 splitWithSuffixSeq "\r\n" inh
198 , mkBench "S.splitOnSeq \"aa\" FL.drain" env $ \inh _ ->
200 , mkBench "S.splitOnSeq \"aaaa\" FL.drain" env $ \inh _ ->
201 splitOnSeq "aaaa" inh
202 , mkBench "S.splitOnSeq \"abcdefgh\" FL.drain" env $ \inh _ ->
203 splitOnSeq "abcdefgh" inh
204 , mkBench "S.splitOnSeq \"abcdefghi\" FL.drain" env $ \inh _ ->
205 splitOnSeq "abcdefghi" inh
206 , mkBench "S.splitOnSeq \"catcatcatcatcat\" FL.drain" env $ \inh _ ->
207 splitOnSeq "catcatcatcatcat" inh
208 , mkBench "S.splitOnSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
209 env $ \inh _ -> splitOnSeq "abcdefghijklmnopqrstuvwxyz" inh
210 , mkBench "S.splitOnSeq 100k long pattern"
211 env $ \inh _ -> splitOnSeq100k inh
212 , mkBenchSmall "S.splitOnSuffixSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
213 env $ \inh _ -> splitOnSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
214 , mkBenchSmall "S.splitWithSuffixSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
215 env $ \inh _ -> splitWithSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
219-- | Split on a character sequence.
220splitOnSeqUtf8 :: String -> Handle -> IO Int
221splitOnSeqUtf8 str inh =
222 (S.length $ IP.splitOnSeq (A.fromList str) FL.drain
223 $ IUS.decodeUtf8Arrays
224 $ IFH.getChunks inh) -- >>= print
226o_1_space_reduce_toChunks_split :: BenchEnv -> [Benchmark]
227o_1_space_reduce_toChunks_split env =
228 [ bgroup "split/toChunks"
229 [ mkBenchSmall ("S.splitOnSeqUtf8 \"abcdefgh\" FL.drain "
230 ++ ". US.decodeUtf8Arrays") env $ \inh _ ->
231 splitOnSeqUtf8 "abcdefgh" inh
232 , mkBenchSmall "S.splitOnSeqUtf8 \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
233 env $ \inh _ -> splitOnSeqUtf8 "abcdefghijklmnopqrstuvwxyz" inh
237benchmarks :: String -> BenchEnv -> [Benchmark]
238benchmarks moduleName env =
239 [ bgroup (o_1_space_prefix moduleName) $ concat
240 [ o_1_space_reduce_read_split env
241 , o_1_space_reduce_toChunks_split env
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list