on 95ebb7b help sign in
262 lines 8.9 kB history raw
1-- |
2-- Module : Streamly.Benchmark.FileSystem.Handle
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD3-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 Handle.ReadWrite
22 (allBenchmarks)
23where
25import System.IO (Handle)
26import Prelude hiding (last, length)
27import Streamly.Internal.Data.Array.Storable.Foreign.Types (defaultChunkSize)
29import qualified Streamly.FileSystem.Handle as FH
30import qualified Streamly.Internal.Data.Unfold as IUF
31import qualified Streamly.Internal.FileSystem.Handle as IFH
32import qualified Streamly.Internal.Memory.ArrayStream as AS
33import qualified Streamly.Data.Array.Storable.Foreign as A
34import qualified Streamly.Prelude as S
36import Gauge hiding (env)
37import Streamly.Benchmark.Common.Handle
39#ifdef INSPECTION
40import Foreign.Storable (Storable)
41import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
43import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
44import qualified Streamly.Internal.Data.Tuple.Strict as Strict
45import qualified Streamly.Internal.Data.Array.Stream.Mut.Foreign as MAS
46import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as AT
47import qualified Streamly.Internal.Data.Array.Storable.Foreign.Mut.Types as MA
49import Test.Inspection
50#endif
52-------------------------------------------------------------------------------
53-- copy chunked
54-------------------------------------------------------------------------------
56-- | Copy file
57copyChunks :: Handle -> Handle -> IO ()
58copyChunks inh outh = S.fold (IFH.writeChunks outh) $ IFH.toChunks inh
60#ifdef INSPECTION
61inspect $ hasNoTypeClasses 'copyChunks
62inspect $ 'copyChunks `hasNoType` ''Step
63#endif
65o_1_space_copy_chunked :: BenchEnv -> [Benchmark]
66o_1_space_copy_chunked env =
67 [ bgroup "copy/toChunks"
68 [ mkBench "toNull" env $ \inH _ ->
69 copyChunks inH (nullH env)
70 , mkBench "raw" env $ \inH outH ->
71 copyChunks inH outH
72 ]
73 ]
75-------------------------------------------------------------------------------
76-- copy unfold
77-------------------------------------------------------------------------------
79-- | Copy file
80copyStream :: Handle -> Handle -> IO ()
81copyStream inh outh = S.fold (FH.write outh) (S.unfold FH.read inh)
83#ifdef INSPECTION
84inspect $ hasNoTypeClasses 'copyStream
85inspect $ 'copyStream `hasNoType` ''Step -- S.unfold
86inspect $ 'copyStream `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
87inspect $ 'copyStream `hasNoType` ''MA.ReadUState -- FH.read/A.read
88inspect $ 'copyStream `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
89inspect $ 'copyStream `hasNoType` ''Strict.Tuple3' -- FH.write/chunksOf
90#endif
92o_1_space_copy_read :: BenchEnv -> [Benchmark]
93o_1_space_copy_read env =
94 [ bgroup "copy/read"
95 [ mkBench "rawToNull" env $ \inh _ ->
96 copyStream inh (nullH env)
97 , mkBench "rawToFile" env $ \inh outh ->
98 copyStream inh outh
99 ]
100 ]
102-------------------------------------------------------------------------------
103-- copy stream
104-------------------------------------------------------------------------------
106-- | Send the file contents to /dev/null
107readFromBytesNull :: Handle -> Handle -> IO ()
108readFromBytesNull inh devNull = IFH.fromBytes devNull $ S.unfold FH.read inh
110#ifdef INSPECTION
111inspect $ hasNoTypeClasses 'readFromBytesNull
112inspect $ 'readFromBytesNull `hasNoType` ''Step
113inspect $ 'readFromBytesNull `hasNoType` ''MAS.SpliceState
114inspect $ 'readFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.arraysOf
115inspect $ 'readFromBytesNull `hasNoType` ''D.GroupState
116#endif
118-- | Send the file contents ('defaultChunkSize') to /dev/null
119readWithBufferOfFromBytesNull :: Handle -> Handle -> IO ()
120readWithBufferOfFromBytesNull inh devNull =
121 IFH.fromBytes devNull
122 $ S.unfold FH.readWithBufferOf (defaultChunkSize, inh)
124#ifdef INSPECTION
125inspect $ hasNoTypeClasses 'readWithBufferOfFromBytesNull
126inspect $ 'readWithBufferOfFromBytesNull `hasNoType` ''Step
127inspect $ 'readWithBufferOfFromBytesNull `hasNoType` ''MAS.SpliceState
128inspect $ 'readWithBufferOfFromBytesNull `hasNoType` ''AT.ArrayUnsafe -- FH.fromBytes/S.arraysOf
129inspect $ 'readWithBufferOfFromBytesNull `hasNoType` ''D.GroupState
130#endif
132-- | Send the chunk content ('defaultChunkSize') to /dev/null
133-- Implicitly benchmarked via 'readFromBytesNull'
134_readChunks :: Handle -> Handle -> IO ()
135_readChunks inh devNull = IUF.fold unf fld inh
137 where
139 fld = FH.write devNull
140 unf = IUF.concat FH.readChunks A.read
142-- | Send the chunk content to /dev/null
143-- Implicitly benchmarked via 'readWithBufferOfFromBytesNull'
144_readChunksWithBufferOf :: Handle -> Handle -> IO ()
145_readChunksWithBufferOf inh devNull = IUF.fold unf fld (defaultChunkSize, inh)
147 where
149 fld = FH.write devNull
150 unf = IUF.concat FH.readChunksWithBufferOf A.read
153o_1_space_copy_fromBytes :: BenchEnv -> [Benchmark]
154o_1_space_copy_fromBytes env =
155 [ bgroup "copy/fromBytes"
156 [ mkBench "rawToNull" env $ \inh _ ->
157 readFromBytesNull inh (nullH env)
158 , mkBench "FH.readWithBufferOf" env $ \inh _ ->
159 readWithBufferOfFromBytesNull inh (nullH env)
160 ]
161 ]
163-- | Send the file contents ('defaultChunkSize') to /dev/null
164{-# NOINLINE writeReadWithBufferOf #-}
165writeReadWithBufferOf :: Handle -> Handle -> IO ()
166writeReadWithBufferOf inh devNull = IUF.fold unf fld (defaultChunkSize, inh)
168 where
170 fld = FH.writeWithBufferOf defaultChunkSize devNull
171 unf = FH.readWithBufferOf
173#ifdef INSPECTION
174inspect $ hasNoTypeClasses 'writeReadWithBufferOf
175inspect $ 'writeReadWithBufferOf `hasNoType` ''Step
176inspect $ 'writeReadWithBufferOf `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
177inspect $ 'writeReadWithBufferOf `hasNoType` ''MA.ReadUState -- FH.read/A.read
178inspect $ 'writeReadWithBufferOf `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
179#endif
181-- | Send the file contents ('AT.defaultChunkSize') to /dev/null
182{-# NOINLINE writeRead #-}
183writeRead :: Handle -> Handle -> IO ()
184writeRead inh devNull = IUF.fold unf fld inh
186 where
188 fld = FH.write devNull
189 unf = FH.read
191#ifdef INSPECTION
192inspect $ hasNoTypeClasses 'writeRead
193inspect $ 'writeRead `hasNoType` ''Step
194inspect $ 'writeRead `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
195inspect $ 'writeRead `hasNoType` ''MA.ReadUState -- FH.read/A.read
196inspect $ 'writeRead `hasNoType` ''AT.ArrayUnsafe -- FH.write/writeNUnsafe
197#endif
199o_1_space_copy :: BenchEnv -> [Benchmark]
200o_1_space_copy env =
201 [ bgroup "copy"
202 [ mkBench "FH.write . FH.read" env $ \inh _ ->
203 writeRead inh (nullH env)
204 , mkBench "FH.writeWithBufferOf . FH.readWithBufferOf" env $ \inh _ ->
205 writeReadWithBufferOf inh (nullH env)
206 ]
207 ]
209-------------------------------------------------------------------------------
210-- copy with group/ungroup transformations
211-------------------------------------------------------------------------------
213-- | Lines and unlines
214copyChunksSplitInterposeSuffix :: Handle -> Handle -> IO ()
215copyChunksSplitInterposeSuffix inh outh =
216 S.fold (IFH.write outh)
217 $ AS.interposeSuffix 10
218 $ AS.splitOnSuffix 10
219 $ IFH.toChunks inh
221#ifdef INSPECTION
222inspect $ hasNoTypeClassesExcept 'copyChunksSplitInterposeSuffix [''Storable]
223inspect $ 'copyChunksSplitInterposeSuffix `hasNoType` ''Step
224#endif
226-- | Words and unwords
227copyChunksSplitInterpose :: Handle -> Handle -> IO ()
228copyChunksSplitInterpose inh outh =
229 S.fold (IFH.write outh)
230 $ AS.interpose 32
231 -- XXX this is not correct word splitting combinator
232 $ AS.splitOn 32
233 $ IFH.toChunks inh
235#ifdef INSPECTION
236inspect $ hasNoTypeClassesExcept 'copyChunksSplitInterpose [''Storable]
237inspect $ 'copyChunksSplitInterpose `hasNoType` ''Step
238#endif
240o_1_space_copy_toChunks_group_ungroup :: BenchEnv -> [Benchmark]
241o_1_space_copy_toChunks_group_ungroup env =
242 [ bgroup "copy/toChunks/group-ungroup"
243 [ mkBench "AS.interposeSuffix . AS.splitOnSuffix" env $ \inh outh ->
244 copyChunksSplitInterposeSuffix inh outh
245 , mkBenchSmall "AS.interpose . AS.splitOn" env $ \inh outh ->
246 copyChunksSplitInterpose inh outh
247 ]
248 ]
251-------------------------------------------------------------------------------
252--
253-------------------------------------------------------------------------------
255allBenchmarks :: BenchEnv -> [Benchmark]
256allBenchmarks env = Prelude.concat
257 [ o_1_space_copy_chunked env
258 , o_1_space_copy_read env
259 , o_1_space_copy_fromBytes env
260 , o_1_space_copy env
261 , o_1_space_copy_toChunks_group_ungroup env
262 ]