on 8dadcad help sign in
199 lines 5.4 kB history raw
1-- |
2-- Module : Streamly.Benchmark.FileIO.Array
3-- Copyright : (c) 2019 Composewell Technologies
4--
5-- License : BSD3
6-- Maintainer : harendra.kumar@gmail.com
7-- Stability : experimental
8-- Portability : GHC
10{-# LANGUAGE CPP #-}
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 Streamly.Benchmark.FileIO.Array
22 (
23 last
24 , countBytes
25 , countLines
26 , countWords
27 , sumBytes
28 , cat
29 , copy
30 , linesUnlinesCopy
31 , wordsUnwordsCopy
32 , decodeUtf8Lenient
33 , copyCodecUtf8Lenient
34 )
35where
37import Data.Functor.Identity (runIdentity)
38import Data.Word (Word8)
39import System.IO (Handle)
40import Prelude hiding (last)
42import qualified Streamly.FileSystem.Handle as FH
43import qualified Streamly.Memory.Array as A
44import qualified Streamly.Prelude as S
45import qualified Streamly.Data.String as SS
47import qualified Streamly.Internal.FileSystem.Handle as IFH
48import qualified Streamly.Internal.Prelude as Internal
49import qualified Streamly.Internal.Memory.Array as IA
50import qualified Streamly.Internal.Memory.ArrayStream as AS
52#ifdef INSPECTION
53import Foreign.Storable (Storable)
54import Streamly.Streams.StreamD.Type (Step(..))
55import Test.Inspection
56#endif
58-- | Get the last byte from a file bytestream.
59{-# INLINE last #-}
60last :: Handle -> IO (Maybe Word8)
61last inh = do
62 let s = IFH.readArrays inh
63 larr <- S.last s
64 return $ case larr of
65 Nothing -> Nothing
66 Just arr -> A.readIndex arr (A.length arr - 1)
68#ifdef INSPECTION
69inspect $ hasNoTypeClasses 'last
70inspect $ 'last `hasNoType` ''Step
71#endif
73-- | Count the number of bytes in a file.
74{-# INLINE countBytes #-}
75countBytes :: Handle -> IO Int
76countBytes inh =
77 let s = IFH.readArrays inh
78 in S.sum (S.map A.length s)
80#ifdef INSPECTION
81inspect $ hasNoTypeClasses 'countBytes
82inspect $ 'countBytes `hasNoType` ''Step
83#endif
85-- | Count the number of lines in a file.
86{-# INLINE countLines #-}
87countLines :: Handle -> IO Int
88countLines = S.length . AS.splitOnSuffix 10 . IFH.readArrays
90#ifdef INSPECTION
91inspect $ hasNoTypeClasses 'countLines
92inspect $ 'countLines `hasNoType` ''Step
93#endif
95-- XXX use a word splitting combinator instead of splitOn and test it.
96-- | Count the number of lines in a file.
97{-# INLINE countWords #-}
98countWords :: Handle -> IO Int
99countWords = S.length . AS.splitOn 32 . IFH.readArrays
101#ifdef INSPECTION
102inspect $ hasNoTypeClasses 'countWords
103inspect $ 'countWords `hasNoType` ''Step
104#endif
106-- | Sum the bytes in a file.
107{-# INLINE sumBytes #-}
108sumBytes :: Handle -> IO Word8
109sumBytes inh = do
110 let foldlArr' f z = runIdentity . S.foldl' f z . IA.toStream
111 let s = IFH.readArrays inh
112 S.foldl' (\acc arr -> acc + foldlArr' (+) 0 arr) 0 s
114#ifdef INSPECTION
115inspect $ hasNoTypeClasses 'sumBytes
116inspect $ 'sumBytes `hasNoType` ''Step
117#endif
119-- | Send the file contents to /dev/null
120{-# INLINE cat #-}
121cat :: Handle -> Handle -> IO ()
122cat devNull inh =
123 S.fold (IFH.writeArrays devNull) $ IFH.readArraysOf (256*1024) inh
125#ifdef INSPECTION
126inspect $ hasNoTypeClasses 'cat
127inspect $ 'cat `hasNoType` ''Step
128#endif
130-- | Copy file
131{-# INLINE copy #-}
132copy :: Handle -> Handle -> IO ()
133copy inh outh =
134 let s = IFH.readArrays inh
135 in S.fold (IFH.writeArrays outh) s
137#ifdef INSPECTION
138inspect $ hasNoTypeClasses 'copy
139inspect $ 'copy `hasNoType` ''Step
140#endif
142-- | Lines and unlines
143{-# INLINE linesUnlinesCopy #-}
144linesUnlinesCopy :: Handle -> Handle -> IO ()
145linesUnlinesCopy inh outh =
146 S.fold (IFH.writeArraysInChunksOf (1024*1024) outh)
147 $ Internal.insertAfterEach (return $ A.fromList [10])
148 $ AS.splitOnSuffix 10
149 $ IFH.readArraysOf (1024*1024) inh
151#ifdef INSPECTION
152inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
153-- inspect $ 'linesUnlinesCopy `hasNoType` ''Step
154#endif
156-- | Words and unwords
157{-# INLINE wordsUnwordsCopy #-}
158wordsUnwordsCopy :: Handle -> Handle -> IO ()
159wordsUnwordsCopy inh outh =
160 S.fold (IFH.writeArraysInChunksOf (1024*1024) outh)
161 $ S.intersperse (A.fromList [32])
162 -- XXX use a word splitting combinator
163 $ AS.splitOn 32
164 $ IFH.readArraysOf (1024*1024) inh
166#ifdef INSPECTION
167inspect $ hasNoTypeClassesExcept 'wordsUnwordsCopy [''Storable]
168-- inspect $ 'wordsUnwordsCopy `hasNoType` ''Step
169#endif
171{-# INLINE decodeUtf8Lenient #-}
172decodeUtf8Lenient :: Handle -> IO ()
173decodeUtf8Lenient inh =
174 S.drain
175 $ SS.decodeUtf8ArraysLenient
176 $ IFH.readArraysOf (1024*1024) inh
178#ifdef INSPECTION
179inspect $ hasNoTypeClasses 'decodeUtf8Lenient
180-- inspect $ 'decodeUtf8Lenient `hasNoType` ''Step
181-- inspect $ 'decodeUtf8Lenient `hasNoType` ''AT.FlattenState
182-- inspect $ 'decodeUtf8Lenient `hasNoType` ''D.ConcatMapUState
183#endif
185-- | Copy file
186{-# INLINE copyCodecUtf8Lenient #-}
187copyCodecUtf8Lenient :: Handle -> Handle -> IO ()
188copyCodecUtf8Lenient inh outh =
189 S.fold (FH.write outh)
190 $ SS.encodeUtf8
191 $ SS.decodeUtf8ArraysLenient
192 $ IFH.readArraysOf (1024*1024) inh
194#ifdef INSPECTION
195inspect $ hasNoTypeClasses 'copyCodecUtf8Lenient
196-- inspect $ 'copyCodecUtf8Lenient `hasNoType` ''Step
197-- inspect $ 'copyCodecUtf8Lenient `hasNoType` ''AT.FlattenState
198-- inspect $ 'copyCodecUtf8Lenient `hasNoType` ''D.ConcatMapUState
199#endif