on 4eaeb10 help sign in
241 lines 8.5 kB history raw
1-- |
2-- Module : Stream.Split
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
7-- Portability : GHC
9{-# LANGUAGE CPP #-}
10{-# LANGUAGE ScopedTypeVariables #-}
12#ifdef __HADDOCK_VERSION__
13#undef INSPECTION
14#endif
16#ifdef INSPECTION
17{-# LANGUAGE TemplateHaskell #-}
18{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
19#endif
21module Stream.Split (benchmarks) where
23import Data.Char (ord)
24import Data.Word (Word8)
25import System.IO (Handle)
27import qualified Streamly.FileSystem.Handle as FH
28import qualified Streamly.Internal.Data.Array.Unboxed as A
29import qualified Streamly.Internal.Data.Fold as FL
30import qualified Streamly.Internal.Data.Parser as PR
31import qualified Streamly.Internal.Data.Stream.IsStream as IP
32import qualified Streamly.Internal.FileSystem.Handle as IFH
33import qualified Streamly.Internal.Unicode.Stream as IUS
34import qualified Streamly.Prelude as S
36import Gauge hiding (env)
37import Prelude hiding (last, length)
38import Streamly.Benchmark.Common
39import Streamly.Benchmark.Common.Handle
41#ifdef INSPECTION
42import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
44import qualified Streamly.Internal.Data.Array.Unboxed.Mut.Type as MA
45import qualified Streamly.Internal.Data.Unfold as IUF
47import Test.Inspection
48#endif
50 -------------------------------------------------------------------------------
51-- reduce with splitting transformations
52-------------------------------------------------------------------------------
54lf :: Word8
55lf = fromIntegral (ord '\n')
57toarr :: String -> A.Array Word8
58toarr = A.fromList . map (fromIntegral . ord)
60-- | Split on line feed.
61splitOn :: Handle -> IO Int
62splitOn inh =
63 (S.length $ S.splitOn (== lf) FL.drain
64 $ S.unfold FH.read inh) -- >>= print
66#ifdef INSPECTION
67inspect $ hasNoTypeClasses 'splitOn
68inspect $ 'splitOn `hasNoType` ''Step
69inspect $ 'splitOn `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
70inspect $ 'splitOn `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
71#endif
73-- | Split suffix on line feed.
74splitOnSuffix :: Handle -> IO Int
75splitOnSuffix inh =
76 (S.length $ S.splitOnSuffix (== lf) FL.drain
77 $ S.unfold FH.read inh) -- >>= print
79#ifdef INSPECTION
80inspect $ hasNoTypeClasses 'splitOnSuffix
81inspect $ 'splitOnSuffix `hasNoType` ''Step
82inspect $ 'splitOnSuffix `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
83inspect $ 'splitOnSuffix `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
84#endif
86-- | Split suffix with line feed.
87splitWithSuffix :: Handle -> IO Int
88splitWithSuffix inh =
89 (S.length $ S.splitWithSuffix (== lf) FL.drain
90 $ S.unfold FH.read inh) -- >>= print
92#ifdef INSPECTION
93inspect $ hasNoTypeClasses 'splitWithSuffix
94inspect $ 'splitWithSuffix `hasNoType` ''Step
95inspect $ 'splitWithSuffix `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
96inspect $ 'splitWithSuffix `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
97#endif
99-- | Split on line feed.
100foldManySepBy :: Handle -> IO Int
101foldManySepBy inh =
102 (S.length
103 $ IP.foldMany
104 (FL.takeEndBy_ (== lf) FL.drain)
105 (S.unfold FH.read inh)
106 ) -- >>= print
108-- | Split on line feed.
109parseManySepBy :: Handle -> IO Int
110parseManySepBy inh =
111 (S.length
112 $ IP.parseMany
113 (PR.fromFold $ FL.takeEndBy_ (== lf) FL.drain)
114 (S.unfold FH.read inh)
115 ) -- >>= print
117-- | Words by space
118wordsBy :: Handle -> IO Int
119wordsBy inh =
120 (S.length $ S.wordsBy isSp FL.drain
121 $ S.unfold FH.read inh) -- >>= print
123#ifdef INSPECTION
124inspect $ hasNoTypeClasses 'wordsBy
125inspect $ 'wordsBy `hasNoType` ''Step
126inspect $ 'wordsBy `hasNoType` ''IUF.ConcatState -- FH.read/UF.many
127inspect $ 'wordsBy `hasNoType` ''MA.ArrayUnsafe -- FH.read/A.read
128#endif
130-- | Split on a word8 sequence.
131splitOnSeq :: String -> Handle -> IO Int
132splitOnSeq str inh =
133 (S.length $ IP.splitOnSeq (toarr str) FL.drain
134 $ S.unfold FH.read inh) -- >>= print
136#ifdef INSPECTION
137-- inspect $ hasNoTypeClasses 'splitOnSeq
138-- inspect $ 'splitOnSeq `hasNoType` ''Step
139#endif
141-- | Split on a word8 sequence.
142splitOnSeq100k :: Handle -> IO Int
143splitOnSeq100k inh = do
144 arr <- A.fromStream $ S.replicate 100000 123
145 (S.length $ IP.splitOnSeq arr FL.drain
146 $ S.unfold FH.read inh) -- >>= print
148-- | Split on suffix sequence.
149splitOnSuffixSeq :: String -> Handle -> IO Int
150splitOnSuffixSeq str inh =
151 (S.length $ IP.splitOnSuffixSeq (toarr str) FL.drain
152 $ S.unfold FH.read inh) -- >>= print
154#ifdef INSPECTION
155-- inspect $ hasNoTypeClasses 'splitOnSuffixSeq
156-- inspect $ 'splitOnSuffixSeq `hasNoType` ''Step
157#endif
159-- | Split on suffix sequence.
160splitWithSuffixSeq :: String -> Handle -> IO Int
161splitWithSuffixSeq str inh =
162 S.length $ IP.splitWithSuffixSeq (toarr str) FL.drain
163 $ S.unfold FH.read inh -- >>= print
165o_1_space_reduce_read_split :: BenchEnv -> [Benchmark]
166o_1_space_reduce_read_split env =
167 [ bgroup "split"
168 [ mkBench "S.foldMany (FL.takeEndBy_ (== lf) FL.drain)" env
169 $ \inh _ -> foldManySepBy inh
170 , mkBench "S.parseMany (FL.takeEndBy_ (== lf) FL.drain)" env
171 $ \inh _ -> parseManySepBy inh
172 , mkBench "S.wordsBy isSpace FL.drain" env $ \inh _ ->
173 wordsBy inh
174 , mkBench "S.splitOn (== lf) FL.drain" env $ \inh _ ->
175 splitOn inh
176 , mkBench "S.splitOnSuffix (== lf) FL.drain" env $ \inh _ ->
177 splitOnSuffix inh
178 , mkBench "S.splitWithSuffix (== lf) FL.drain" env $ \inh _ ->
179 splitWithSuffix inh
180 , mkBench "S.splitOnSeq \"\" FL.drain" env $ \inh _ ->
181 splitOnSeq "" inh
182 , mkBench "S.splitOnSuffixSeq \"\" FL.drain" env $ \inh _ ->
183 splitOnSuffixSeq "" inh
184 , mkBench "S.splitOnSeq \"\\n\" FL.drain" env $ \inh _ ->
185 splitOnSeq "\n" inh
186 , mkBench "S.splitOnSuffixSeq \"\\n\" FL.drain" env $ \inh _ ->
187 splitOnSuffixSeq "\n" inh
188 , mkBench "S.splitOnSeq \"a\" FL.drain" env $ \inh _ ->
189 splitOnSeq "a" inh
190 , mkBench "S.splitOnSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
191 splitOnSeq "\r\n" inh
192 , mkBench "S.splitOnSuffixSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
193 splitOnSuffixSeq "\r\n" inh
194 , mkBench "S.splitWithSuffixSeq \"\\r\\n\" FL.drain" env $ \inh _ ->
195 splitWithSuffixSeq "\r\n" inh
196 , mkBench "S.splitOnSeq \"aa\" FL.drain" env $ \inh _ ->
197 splitOnSeq "aa" inh
198 , mkBench "S.splitOnSeq \"aaaa\" FL.drain" env $ \inh _ ->
199 splitOnSeq "aaaa" inh
200 , mkBench "S.splitOnSeq \"abcdefgh\" FL.drain" env $ \inh _ ->
201 splitOnSeq "abcdefgh" inh
202 , mkBench "S.splitOnSeq \"abcdefghi\" FL.drain" env $ \inh _ ->
203 splitOnSeq "abcdefghi" inh
204 , mkBench "S.splitOnSeq \"catcatcatcatcat\" FL.drain" env $ \inh _ ->
205 splitOnSeq "catcatcatcatcat" inh
206 , mkBench "S.splitOnSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
207 env $ \inh _ -> splitOnSeq "abcdefghijklmnopqrstuvwxyz" inh
208 , mkBench "S.splitOnSeq 100k long pattern"
209 env $ \inh _ -> splitOnSeq100k inh
210 , mkBenchSmall "S.splitOnSuffixSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
211 env $ \inh _ -> splitOnSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
212 , mkBenchSmall "S.splitWithSuffixSeq \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
213 env $ \inh _ -> splitWithSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
214 ]
215 ]
217-- | Split on a character sequence.
218splitOnSeqUtf8 :: String -> Handle -> IO Int
219splitOnSeqUtf8 str inh =
220 (S.length $ IP.splitOnSeq (A.fromList str) FL.drain
221 $ IUS.decodeUtf8Arrays
222 $ IFH.getChunks inh) -- >>= print
224o_1_space_reduce_toChunks_split :: BenchEnv -> [Benchmark]
225o_1_space_reduce_toChunks_split env =
226 [ bgroup "split/toChunks"
227 [ mkBenchSmall ("S.splitOnSeqUtf8 \"abcdefgh\" FL.drain "
228 ++ ". US.decodeUtf8Arrays") env $ \inh _ ->
229 splitOnSeqUtf8 "abcdefgh" inh
230 , mkBenchSmall "S.splitOnSeqUtf8 \"abcdefghijklmnopqrstuvwxyz\" FL.drain"
231 env $ \inh _ -> splitOnSeqUtf8 "abcdefghijklmnopqrstuvwxyz" inh
232 ]
233 ]
235benchmarks :: String -> BenchEnv -> [Benchmark]
236benchmarks moduleName env =
237 [ bgroup (o_1_space_prefix moduleName) $ concat
238 [ o_1_space_reduce_read_split env
239 , o_1_space_reduce_toChunks_split env
240 ]
241 ]