on master help sign in
Rename some IO APIs and update documentation
9bf84d4Harendra Kumar
examples/EchoServer.hs+5−2
@@ -12,5 +12,8 @@ main :: IO ()
12main = S.drain
12main = S.drain
13 $ parallely $ S.mapM (useWith echo)
13 $ parallely $ S.mapM (useWith echo)
14 $ serially $ S.unfold TCP.acceptOnPort 8090
14 $ serially $ S.unfold TCP.acceptOnPort 8090
15− where echo sk = S.fold (writeArrays sk) $ S.unfold readArraysOf (32768, sk)
15+ where
16+ echo sk =
17+ S.fold (writeChunks sk)
18+ $ S.unfold readChunksRequestsOf (32768, sk)
16− useWith f sk = finally (liftIO (Net.close sk)) (f sk)
19+ useWith f sk = finally (liftIO (Net.close sk)) (f sk)
examples/FileIOExamples.hs+9−3
@@ -8,13 +8,19 @@ import Data.Char (ord)
8import System.Environment (getArgs)
8import System.Environment (getArgs)
9
9
10cat :: FilePath -> IO ()
10cat :: FilePath -> IO ()
11−cat src = File.writeArrays "/dev/stdout" $ File.toStreamArraysOf (256*1024) src
11+cat src =
12+ File.writeChunks "/dev/stdout"
13+ $ File.toChunksRequestsOf (256*1024) src
12
14
13cp :: FilePath -> FilePath -> IO ()
15cp :: FilePath -> FilePath -> IO ()
14−cp src dst = File.writeArrays dst $ File.toStreamArraysOf (256*1024) src
16+cp src dst =
17+ File.writeChunks dst
18+ $ File.toChunksRequestsOf (256*1024) src
15
19
16append :: FilePath -> FilePath -> IO ()
20append :: FilePath -> FilePath -> IO ()
17−append src dst = File.appendArrays dst $ File.toStreamArraysOf (256*1024) src
21+append src dst =
22+ File.appendChunks dst
23+ $ File.toChunksRequestsOf (256*1024) src
18
24
19ord' :: Num a => Char -> a
25ord' :: Num a => Char -> a
20ord' = (fromIntegral . ord)
26ord' = (fromIntegral . ord)
examples/FromFileClient.hs+2−2
@@ -16,6 +16,6 @@ main :: IO ()
16main =
16main =
17 let sendFile file =
17 let sendFile file =
18 withFile file ReadMode $ \src ->
18 withFile file ReadMode $ \src ->
19− S.fold (TCP.writeArrays (127, 0, 0, 1) 8090)
19+ S.fold (TCP.writeChunks (127, 0, 0, 1) 8090)
20− $ IFH.toStreamArrays src
20+ $ IFH.toChunks src
21 in getArgs >>= S.drain . parallely . S.mapM sendFile . S.fromList
21 in getArgs >>= S.drain . parallely . S.mapM sendFile . S.fromList
examples/HandleIO.hs+10−6
@@ -6,19 +6,23 @@ import qualified Streamly.Internal.FileSystem.Handle as IFH
6import qualified Streamly.FileSystem.Handle as FH
6import qualified Streamly.FileSystem.Handle as FH
7import qualified System.IO as FH
7import qualified System.IO as FH
8-- import qualified Streamly.FileSystem.FD as FH
8-- import qualified Streamly.FileSystem.FD as FH
9−-- import qualified Streamly.String as SS
9+-- import qualified Streamly.Data.Unicode.Stream as US
10
10
11import Data.Char (ord)
11import Data.Char (ord)
12import System.Environment (getArgs)
12import System.Environment (getArgs)
13import System.IO (IOMode(..), hSeek, SeekMode(..))
13import System.IO (IOMode(..), hSeek, SeekMode(..))
14
14
15cat :: FH.Handle -> IO ()
15cat :: FH.Handle -> IO ()
16−cat src = S.fold (IFH.writeArrays FH.stdout) $ IFH.toStreamArraysOf (256*1024) src
16+cat src =
17+ S.fold (FH.writeChunks FH.stdout)
18+ $ IFH.toChunksRequestsOf (256*1024) src
17-- byte stream version
19-- byte stream version
18-- cat src = S.fold (FH.write FH.stdout) $ FH.read src
20-- cat src = S.fold (FH.write FH.stdout) $ FH.read src
19
21
20cp :: FH.Handle -> FH.Handle -> IO ()
22cp :: FH.Handle -> FH.Handle -> IO ()
21−cp src dst = S.fold (IFH.writeArrays dst) $ IFH.toStreamArraysOf (256*1024) src
23+cp src dst =
24+ S.fold (FH.writeChunks dst)
25+ $ IFH.toChunksRequestsOf (256*1024) src
22-- byte stream version
26-- byte stream version
23-- cp src dst = S.fold (FH.write dst) $ FH.read src
27-- cp src dst = S.fold (FH.write dst) $ FH.read src
24
28
@@ -28,12 +32,12 @@ ord' = (fromIntegral . ord)
28wcl :: FH.Handle -> IO ()
32wcl :: FH.Handle -> IO ()
29wcl src = print =<< (S.length
33wcl src = print =<< (S.length
30 $ AS.splitOn 10
34 $ AS.splitOn 10
31− $ IFH.toStreamArrays src)
35+ $ IFH.toChunks src)
32{-
36{-
33-- Char stream version
37-- Char stream version
34wcl src = print =<< (S.length
38wcl src = print =<< (S.length
35− $ flip SS.foldLines FL.drain
39+ $ flip US.lines FL.drain
36− $ SS.decodeChar8
40+ $ US.decodeLatin1
37 $ FH.read src)
41 $ FH.read src)
38-}
42-}
39
43
examples/WordCount.hs+1−1
@@ -608,7 +608,7 @@ wc_mwl_parallel src n = do
608 $ S.aheadly
608 $ S.aheadly
609 $ S.maxThreads numCapabilities
609 $ S.maxThreads numCapabilities
610 $ S.mapM (countArray)
610 $ S.mapM (countArray)
611− $ S.unfold FH.readArraysOf (n, src)
611+ $ S.unfold FH.readChunksRequestsOf (n, src)
612
612
613-------------------------------------------------------------------------------
613-------------------------------------------------------------------------------
614-- Main
614-- Main
src/Streamly/Benchmark/FileIO/Array.hs+20−20
@@ -63,7 +63,7 @@ import Test.Inspection
63{-# INLINE last #-}
63{-# INLINE last #-}
64last :: Handle -> IO (Maybe Word8)
64last :: Handle -> IO (Maybe Word8)
65last inh = do
65last inh = do
66− let s = IFH.toStreamArrays inh
66+ let s = IFH.toChunks inh
67 larr <- S.last s
67 larr <- S.last s
68 return $ case larr of
68 return $ case larr of
69 Nothing -> Nothing
69 Nothing -> Nothing
@@ -78,7 +78,7 @@ inspect $ 'last `hasNoType` ''Step
78{-# INLINE countBytes #-}
78{-# INLINE countBytes #-}
79countBytes :: Handle -> IO Int
79countBytes :: Handle -> IO Int
80countBytes inh =
80countBytes inh =
81− let s = IFH.toStreamArrays inh
81+ let s = IFH.toChunks inh
82 in S.sum (S.map A.length s)
82 in S.sum (S.map A.length s)
83
83
84#ifdef INSPECTION
84#ifdef INSPECTION
@@ -89,7 +89,7 @@ inspect $ 'countBytes `hasNoType` ''Step
89-- | Count the number of lines in a file.
89-- | Count the number of lines in a file.
90{-# INLINE countLines #-}
90{-# INLINE countLines #-}
91countLines :: Handle -> IO Int
91countLines :: Handle -> IO Int
92−countLines = S.length . AS.splitOnSuffix 10 . IFH.toStreamArrays
92+countLines = S.length . AS.splitOnSuffix 10 . IFH.toChunks
93
93
94#ifdef INSPECTION
94#ifdef INSPECTION
95inspect $ hasNoTypeClasses 'countLines
95inspect $ hasNoTypeClasses 'countLines
@@ -100,7 +100,7 @@ inspect $ 'countLines `hasNoType` ''Step
100-- | Count the number of lines in a file.
100-- | Count the number of lines in a file.
101{-# INLINE countWords #-}
101{-# INLINE countWords #-}
102countWords :: Handle -> IO Int
102countWords :: Handle -> IO Int
103−countWords = S.length . AS.splitOn 32 . IFH.toStreamArrays
103+countWords = S.length . AS.splitOn 32 . IFH.toChunks
104
104
105#ifdef INSPECTION
105#ifdef INSPECTION
106inspect $ hasNoTypeClasses 'countWords
106inspect $ hasNoTypeClasses 'countWords
@@ -112,7 +112,7 @@ inspect $ 'countWords `hasNoType` ''Step
112sumBytes :: Handle -> IO Word8
112sumBytes :: Handle -> IO Word8
113sumBytes inh = do
113sumBytes inh = do
114 let foldlArr' f z = runIdentity . S.foldl' f z . IA.toStream
114 let foldlArr' f z = runIdentity . S.foldl' f z . IA.toStream
115− let s = IFH.toStreamArrays inh
115+ let s = IFH.toChunks inh
116 S.foldl' (\acc arr -> acc + foldlArr' (+) 0 arr) 0 s
116 S.foldl' (\acc arr -> acc + foldlArr' (+) 0 arr) 0 s
117
117
118#ifdef INSPECTION
118#ifdef INSPECTION
@@ -124,7 +124,7 @@ inspect $ 'sumBytes `hasNoType` ''Step
124{-# INLINE cat #-}
124{-# INLINE cat #-}
125cat :: Handle -> Handle -> IO ()
125cat :: Handle -> Handle -> IO ()
126cat devNull inh =
126cat devNull inh =
127− S.fold (IFH.writeArrays devNull) $ IFH.toStreamArraysOf (256*1024) inh
127+ S.fold (IFH.writeChunks devNull) $ IFH.toChunksRequestsOf (256*1024) inh
128
128
129#ifdef INSPECTION
129#ifdef INSPECTION
130inspect $ hasNoTypeClasses 'cat
130inspect $ hasNoTypeClasses 'cat
@@ -136,8 +136,8 @@ inspect $ 'cat `hasNoType` ''Step
136catBracket :: Handle -> Handle -> IO ()
136catBracket :: Handle -> Handle -> IO ()
137catBracket devNull inh =
137catBracket devNull inh =
138 let readEx = IUF.bracket return (\_ -> hClose inh)
138 let readEx = IUF.bracket return (\_ -> hClose inh)
139− (IUF.supplyFirst FH.readArraysOf (256*1024))
139+ (IUF.supplyFirst FH.readChunksRequestsOf (256*1024))
140− in IUF.fold readEx (IFH.writeArrays devNull) inh
140+ in IUF.fold readEx (IFH.writeChunks devNull) inh
141
141
142#ifdef INSPECTION
142#ifdef INSPECTION
143inspect $ hasNoTypeClasses 'catBracket
143inspect $ hasNoTypeClasses 'catBracket
@@ -149,8 +149,8 @@ inspect $ hasNoTypeClasses 'catBracket
149catBracketStream :: Handle -> Handle -> IO ()
149catBracketStream :: Handle -> Handle -> IO ()
150catBracketStream devNull inh =
150catBracketStream devNull inh =
151 let readEx = S.bracket (return ()) (\_ -> hClose inh)
151 let readEx = S.bracket (return ()) (\_ -> hClose inh)
152− (\_ -> IFH.toStreamArraysOf (256*1024) inh)
152+ (\_ -> IFH.toChunksRequestsOf (256*1024) inh)
153− in S.fold (IFH.writeArrays devNull) $ readEx
153+ in S.fold (IFH.writeChunks devNull) $ readEx
154
154
155#ifdef INSPECTION
155#ifdef INSPECTION
156inspect $ hasNoTypeClasses 'catBracketStream
156inspect $ hasNoTypeClasses 'catBracketStream
@@ -162,8 +162,8 @@ inspect $ hasNoTypeClasses 'catBracketStream
162catOnException :: Handle -> Handle -> IO ()
162catOnException :: Handle -> Handle -> IO ()
163catOnException devNull inh =
163catOnException devNull inh =
164 let readEx = IUF.onException (\_ -> hClose inh)
164 let readEx = IUF.onException (\_ -> hClose inh)
165− (IUF.supplyFirst FH.readArraysOf (256*1024))
165+ (IUF.supplyFirst FH.readChunksRequestsOf (256*1024))
166− in IUF.fold readEx (IFH.writeArrays devNull) inh
166+ in IUF.fold readEx (IFH.writeChunks devNull) inh
167
167
168#ifdef INSPECTION
168#ifdef INSPECTION
169inspect $ hasNoTypeClasses 'catOnException
169inspect $ hasNoTypeClasses 'catOnException
@@ -174,8 +174,8 @@ inspect $ hasNoTypeClasses 'catOnException
174{-# INLINE copy #-}
174{-# INLINE copy #-}
175copy :: Handle -> Handle -> IO ()
175copy :: Handle -> Handle -> IO ()
176copy inh outh =
176copy inh outh =
177− let s = IFH.toStreamArrays inh
177+ let s = IFH.toChunks inh
178− in S.fold (IFH.writeArrays outh) s
178+ in S.fold (IFH.writeChunks outh) s
179
179
180#ifdef INSPECTION
180#ifdef INSPECTION
181inspect $ hasNoTypeClasses 'copy
181inspect $ hasNoTypeClasses 'copy
@@ -186,10 +186,10 @@ inspect $ 'copy `hasNoType` ''Step
186{-# INLINE linesUnlinesCopy #-}
186{-# INLINE linesUnlinesCopy #-}
187linesUnlinesCopy :: Handle -> Handle -> IO ()
187linesUnlinesCopy :: Handle -> Handle -> IO ()
188linesUnlinesCopy inh outh =
188linesUnlinesCopy inh outh =
189− S.fold (IFH.writeInChunksOf (1024*1024) outh)
189+ S.fold (IFH.writeRequestsOf (1024*1024) outh)
190 $ AS.interposeSuffix 10
190 $ AS.interposeSuffix 10
191 $ AS.splitOnSuffix 10
191 $ AS.splitOnSuffix 10
192− $ IFH.toStreamArraysOf (1024*1024) inh
192+ $ IFH.toChunksRequestsOf (1024*1024) inh
193
193
194#ifdef INSPECTION
194#ifdef INSPECTION
195inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
195inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
@@ -200,11 +200,11 @@ inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
200{-# INLINE wordsUnwordsCopy #-}
200{-# INLINE wordsUnwordsCopy #-}
201wordsUnwordsCopy :: Handle -> Handle -> IO ()
201wordsUnwordsCopy :: Handle -> Handle -> IO ()
202wordsUnwordsCopy inh outh =
202wordsUnwordsCopy inh outh =
203− S.fold (IFH.writeInChunksOf (1024*1024) outh)
203+ S.fold (IFH.writeRequestsOf (1024*1024) outh)
204 $ AS.interpose 32
204 $ AS.interpose 32
205 -- XXX this is not correct word splitting combinator
205 -- XXX this is not correct word splitting combinator
206 $ AS.splitOn 32
206 $ AS.splitOn 32
207− $ IFH.toStreamArraysOf (1024*1024) inh
207+ $ IFH.toChunksRequestsOf (1024*1024) inh
208
208
209#ifdef INSPECTION
209#ifdef INSPECTION
210inspect $ hasNoTypeClassesExcept 'wordsUnwordsCopy [''Storable]
210inspect $ hasNoTypeClassesExcept 'wordsUnwordsCopy [''Storable]
@@ -216,7 +216,7 @@ decodeUtf8Lenient :: Handle -> IO ()
216decodeUtf8Lenient inh =
216decodeUtf8Lenient inh =
217 S.drain
217 S.drain
218 $ IUS.decodeUtf8ArraysLenient
218 $ IUS.decodeUtf8ArraysLenient
219− $ IFH.toStreamArraysOf (1024*1024) inh
219+ $ IFH.toChunksRequestsOf (1024*1024) inh
220
220
221#ifdef INSPECTION
221#ifdef INSPECTION
222inspect $ hasNoTypeClasses 'decodeUtf8Lenient
222inspect $ hasNoTypeClasses 'decodeUtf8Lenient
@@ -232,7 +232,7 @@ copyCodecUtf8Lenient inh outh =
232 S.fold (FH.write outh)
232 S.fold (FH.write outh)
233 $ SS.encodeUtf8
233 $ SS.encodeUtf8
234 $ IUS.decodeUtf8ArraysLenient
234 $ IUS.decodeUtf8ArraysLenient
235− $ IFH.toStreamArraysOf (1024*1024) inh
235+ $ IFH.toChunksRequestsOf (1024*1024) inh
236
236
237#ifdef INSPECTION
237#ifdef INSPECTION
238inspect $ hasNoTypeClasses 'copyCodecUtf8Lenient
238inspect $ hasNoTypeClasses 'copyCodecUtf8Lenient
src/Streamly/Benchmark/FileIO/Stream.hs+2−2
@@ -153,7 +153,7 @@ countLinesU inh =
153 S.length
153 S.length
154 $ IUS.lines FL.drain
154 $ IUS.lines FL.drain
155 $ SS.decodeLatin1
155 $ SS.decodeLatin1
156− $ S.concatUnfold A.read (IFH.toStreamArrays inh)
156+ $ S.concatUnfold A.read (IFH.toChunks inh)
157
157
158#ifdef INSPECTION
158#ifdef INSPECTION
159inspect $ hasNoTypeClasses 'countLinesU
159inspect $ hasNoTypeClasses 'countLinesU
@@ -600,7 +600,7 @@ splitOnSeqUtf8 :: String -> Handle -> IO Int
600splitOnSeqUtf8 str inh =
600splitOnSeqUtf8 str inh =
601 (S.length $ IP.splitOnSeq (A.fromList str) FL.drain
601 (S.length $ IP.splitOnSeq (A.fromList str) FL.drain
602 $ IUS.decodeUtf8ArraysLenient
602 $ IUS.decodeUtf8ArraysLenient
603− $ IFH.toStreamArrays inh) -- >>= print
603+ $ IFH.toChunks inh) -- >>= print
604
604
605-- | Split on suffix sequence.
605-- | Split on suffix sequence.
606{-# INLINE splitOnSuffixSeq #-}
606{-# INLINE splitOnSuffixSeq #-}
src/Streamly/FileSystem/Handle.hs+22−37
@@ -25,8 +25,20 @@
25-- 'NewLineMode', and 'Buffering' options of the underlying handle provided by
25-- 'NewLineMode', and 'Buffering' options of the underlying handle provided by
26-- GHC are not needed and ignored.
26-- GHC are not needed and ignored.
27--
27--
28+-- = Programmer Notes
29+--
28-- > import qualified Streamly.FileSystem.Handle as FH
30-- > import qualified Streamly.FileSystem.Handle as FH
29--
31--
32+-- For additional, experimental APIs take a look at
33+-- "Streamly.Internal.FileSystem.Handle" module.
34+--
35+-- = Performance Notes
36+--
37+-- In some cases the stream type based APIs in the
38+-- "Streamly.Internal.FileSystem.Handle" module may be more efficient compared
39+-- to the unfold/fold based APIs exposed from this module because of better
40+-- fusion by GHC. However, with the streamly fusion GHC plugin (upcoming) these
41+-- APIs would perform as well as the stream based APIs in all cases.
30
42
31-- IO APIs are divided into two categories, sequential streaming IO APIs and
43-- IO APIs are divided into two categories, sequential streaming IO APIs and
32-- random access IO APIs.
44-- random access IO APIs.
@@ -37,12 +49,14 @@ module Streamly.FileSystem.Handle
37 -- | Stream data to or from a file or device sequentially. When reading,
49 -- | Stream data to or from a file or device sequentially. When reading,
38 -- the stream is lazy and generated on-demand as the consumer consumes it.
50 -- the stream is lazy and generated on-demand as the consumer consumes it.
39 -- Read IO requests to the IO device are performed in chunks limited to a
51 -- Read IO requests to the IO device are performed in chunks limited to a
40− -- maximum size of 32KiB, this is referred to as @defaultChunkSize@ in the
52+ -- maximum size of 32KiB, this is referred to as
53+ -- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' in the
41 -- documentation. One IO request may or may not read the full
54 -- documentation. One IO request may or may not read the full
42 -- chunk. If the whole stream is not consumed, it is possible that we may
55 -- chunk. If the whole stream is not consumed, it is possible that we may
43 -- read slightly more from the IO device than what the consumer needed.
56 -- read slightly more from the IO device than what the consumer needed.
44 -- Unless specified otherwise in the API, writes are collected into chunks
57 -- Unless specified otherwise in the API, writes are collected into chunks
58+ -- of 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before they
45− -- of @defaultChunkSize@ before they are written to the IO device.
59+ -- are written to the IO device.
46
60
47 -- Streaming APIs work for all kind of devices, seekable or non-seekable;
61 -- Streaming APIs work for all kind of devices, seekable or non-seekable;
48 -- including disks, files, memory devices, terminals, pipes, sockets and
62 -- including disks, files, memory devices, terminals, pipes, sockets and
@@ -57,49 +71,20 @@ module Streamly.FileSystem.Handle
57 -- position of the file handle. The stream ends as soon as EOF is
71 -- position of the file handle. The stream ends as soon as EOF is
58 -- encountered.
72 -- encountered.
59
73
60− -- XXX once we have APIs to read any type 'a' the array stream
61− -- reading/writing APIs can be expressed in terms of the polymorphic API.
62 read
74 read
63− -- , readUtf8
75+ , readRequestsOf
64− -- , readLines
76+ , readChunks
65− -- , readFrames
77+ , readChunksRequestsOf
66− , readInChunksOf
67− , readArraysOf
68− , readArrays
69
78
70 -- ** Write to Handle
79 -- ** Write to Handle
71 -- | 'TextEncoding', 'NewLineMode', and 'Buffering' options of the
80 -- | 'TextEncoding', 'NewLineMode', and 'Buffering' options of the
72 -- underlying handle are ignored. The write occurs from the current seek
81 -- underlying handle are ignored. The write occurs from the current seek
73 -- position of the file handle. The write behavior depends on the 'IOMode'
82 -- position of the file handle. The write behavior depends on the 'IOMode'
74 -- of the handle.
83 -- of the handle.
75− --
76− , write
77− -- , writeUtf8
78− -- , writeUtf8ByLines
79− -- , writeByFrames
80− , writeInChunksOf
81− , writeArrays
82−
83− -- -- * Random Access (Seek)
84− -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
85− -- files that have random access or seek capability. This type of devices
86− -- include disks, files, memory devices and exclude terminals, pipes,
87− -- sockets and fifos.
88− --
89− -- , readIndex
90− -- XXX we can make the names consistent with the enumerate APIs. For
91− -- example, readFromTo, readFromToUp, readFromToDn, readFrom etc.
92− -- , readSlice
93− -- , readSliceRev
94− -- , readAt -- read from a given position to th end of file
95− -- , readSliceArrayUpto
96− -- , readSliceArrayOf
97
84
98− -- , writeIndex
85+ , write
99− -- , writeSlice
86+ , writeRequestsOf
100− -- , writeSliceRev
87+ , writeChunks
101− -- , writeAt -- start writing at the given position
102− -- , writeSliceArray
103 )
88 )
104where
89where
105
90
src/Streamly/Internal/FileSystem/File.hs+37−36
@@ -63,27 +63,27 @@ module Streamly.Internal.FileSystem.File
63 -- -- * Array Read
63 -- -- * Array Read
64 -- , readArrayOf
64 -- , readArrayOf
65
65
66− , toStreamArraysOf
66+ , toChunksRequestsOf
67− -- , toStreamArraysOf
67+ -- , toChunksRequestsOf
68− , toStreamArrays
68+ , toChunks
69
69
70 -- ** Write To File
70 -- ** Write To File
71 , write
71 , write
72 -- , writeUtf8
72 -- , writeUtf8
73 -- , writeUtf8ByLines
73 -- , writeUtf8ByLines
74 -- , writeByFrames
74 -- , writeByFrames
75− , writeInChunksOf
75+ , writeRequestsOf
76
76
77 -- -- * Array Write
77 -- -- * Array Write
78 , writeArray
78 , writeArray
79− , writeArrays
79+ , writeChunks
80
80
81 -- ** Append To File
81 -- ** Append To File
82 , append
82 , append
83− , appendByChunks
83+ , appendRequestsOf
84 -- , appendShared
84 -- , appendShared
85 , appendArray
85 , appendArray
86− , appendArrays
86+ , appendChunks
87
87
88 -- -- * Random Access (Seek)
88 -- -- * Random Access (Seek)
89 -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
89 -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
@@ -182,27 +182,28 @@ appendArray file arr = SIO.withFile file AppendMode (\h -> FH.writeArray h arr)
182-- Stream of Arrays IO
182-- Stream of Arrays IO
183-------------------------------------------------------------------------------
183-------------------------------------------------------------------------------
184
184
185−-- | @toStreamArraysOf size file@ reads a stream of arrays from file @file@.
185+-- | @toChunksRequestsOf size file@ reads a stream of arrays from file @file@.
186-- The maximum size of a single array is specified by @size@. The actual size
186-- The maximum size of a single array is specified by @size@. The actual size
187-- read may be less than or equal to @size@.
187-- read may be less than or equal to @size@.
188−{-# INLINABLE toStreamArraysOf #-}
188+{-# INLINABLE toChunksRequestsOf #-}
189−toStreamArraysOf :: (IsStream t, MonadCatch m, MonadIO m)
189+toChunksRequestsOf :: (IsStream t, MonadCatch m, MonadIO m)
190 => Int -> FilePath -> t m (Array Word8)
190 => Int -> FilePath -> t m (Array Word8)
191+toChunksRequestsOf size file =
191−toStreamArraysOf size file = withFile file ReadMode (FH.toStreamArraysOf size)
192+ withFile file ReadMode (FH.toChunksRequestsOf size)
192
193
193-- XXX read 'Array a' instead of Word8
194-- XXX read 'Array a' instead of Word8
194--
195--
195−-- | @toStreamArrays file@ reads a stream of arrays from file @file@.
196+-- | @toChunks file@ reads a stream of arrays from file @file@.
196-- The maximum size of a single array is limited to @defaultChunkSize@. The
197-- The maximum size of a single array is limited to @defaultChunkSize@. The
197-- actual size read may be less than @defaultChunkSize@.
198-- actual size read may be less than @defaultChunkSize@.
198--
199--
199−-- > toStreamArrays = toStreamArraysOf defaultChunkSize
200+-- > toChunks = toChunksRequestsOf defaultChunkSize
200--
201--
201-- @since 0.7.0
202-- @since 0.7.0
202−{-# INLINE toStreamArrays #-}
203+{-# INLINE toChunks #-}
203−toStreamArrays :: (IsStream t, MonadCatch m, MonadIO m)
204+toChunks :: (IsStream t, MonadCatch m, MonadIO m)
204 => FilePath -> t m (Array Word8)
205 => FilePath -> t m (Array Word8)
205−toStreamArrays = toStreamArraysOf defaultChunkSize
206+toChunks = toChunksRequestsOf defaultChunkSize
206
207
207-------------------------------------------------------------------------------
208-------------------------------------------------------------------------------
208-- Read File to Stream
209-- Read File to Stream
@@ -219,7 +220,7 @@ toStreamArrays = toStreamArraysOf defaultChunkSize
219--
220--
220{-# INLINE readInChunksOf #-}
221{-# INLINE readInChunksOf #-}
221readInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
222readInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
222−readInChunksOf chunkSize h = A.flattenArrays $ toStreamArraysOf chunkSize h
223+readInChunksOf chunkSize h = A.flattenArrays $ toChunksRequestsOf chunkSize h
223-}
224-}
224
225
225-- TODO
226-- TODO
@@ -233,7 +234,7 @@ readInChunksOf chunkSize h = A.flattenArrays $ toStreamArraysOf chunkSize h
233-- @since 0.7.0
234-- @since 0.7.0
234{-# INLINE read #-}
235{-# INLINE read #-}
235read :: (IsStream t, MonadCatch m, MonadIO m) => FilePath -> t m Word8
236read :: (IsStream t, MonadCatch m, MonadIO m) => FilePath -> t m Word8
236−read file = AS.concat $ withFile file ReadMode FH.toStreamArrays
237+read file = AS.concat $ withFile file ReadMode FH.toChunks
237
238
238{-
239{-
239-- | Generate a stream of elements of the given type from a file 'Handle'. The
240-- | Generate a stream of elements of the given type from a file 'Handle'. The
@@ -259,19 +260,19 @@ readTailForever = undefined
259-- Writing
260-- Writing
260-------------------------------------------------------------------------------
261-------------------------------------------------------------------------------
261
262
262−{-# INLINE writeArraysMode #-}
263+{-# INLINE writeChunksMode #-}
263−writeArraysMode :: (MonadAsync m, MonadCatch m, Storable a)
264+writeChunksMode :: (MonadAsync m, MonadCatch m, Storable a)
264 => IOMode -> FilePath -> SerialT m (Array a) -> m ()
265 => IOMode -> FilePath -> SerialT m (Array a) -> m ()
265−writeArraysMode mode file xs = S.drain $
266+writeChunksMode mode file xs = S.drain $
266 withFile file mode (\h -> S.mapM (liftIO . FH.writeArray h) xs)
267 withFile file mode (\h -> S.mapM (liftIO . FH.writeArray h) xs)
267
268
268-- | Write a stream of arrays to a file. Overwrites the file if it exists.
269-- | Write a stream of arrays to a file. Overwrites the file if it exists.
269--
270--
270-- @since 0.7.0
271-- @since 0.7.0
271−{-# INLINE writeArrays #-}
272+{-# INLINE writeChunks #-}
272−writeArrays :: (MonadAsync m, MonadCatch m, Storable a)
273+writeChunks :: (MonadAsync m, MonadCatch m, Storable a)
273 => FilePath -> SerialT m (Array a) -> m ()
274 => FilePath -> SerialT m (Array a) -> m ()
274−writeArrays = writeArraysMode WriteMode
275+writeChunks = writeChunksMode WriteMode
275
276
276-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
277-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
277--
278--
@@ -286,12 +287,12 @@ writeArrays = writeArraysMode WriteMode
286-- input elements.
287-- input elements.
287--
288--
288-- @since 0.7.0
289-- @since 0.7.0
289−{-# INLINE writeInChunksOf #-}
290+{-# INLINE writeRequestsOf #-}
290−writeInChunksOf :: (MonadAsync m, MonadCatch m)
291+writeRequestsOf :: (MonadAsync m, MonadCatch m)
291 => Int -> FilePath -> SerialT m Word8 -> m ()
292 => Int -> FilePath -> SerialT m Word8 -> m ()
292−writeInChunksOf n file xs = writeArrays file $ AS.arraysOf n xs
293+writeRequestsOf n file xs = writeChunks file $ AS.arraysOf n xs
293
294
294−-- > write = 'writeInChunksOf' defaultChunkSize
295+-- > write = 'writeRequestsOf' defaultChunkSize
295--
296--
296-- | Write a byte stream to a file. Combines the bytes in chunks of size
297-- | Write a byte stream to a file. Combines the bytes in chunks of size
297-- up to 'A.defaultChunkSize' before writing. If the file exists it is
298-- up to 'A.defaultChunkSize' before writing. If the file exists it is
@@ -301,7 +302,7 @@ writeInChunksOf n file xs = writeArrays file $ AS.arraysOf n xs
301-- @since 0.7.0
302-- @since 0.7.0
302{-# INLINE write #-}
303{-# INLINE write #-}
303write :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
304write :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
304−write = writeInChunksOf defaultChunkSize
305+write = writeRequestsOf defaultChunkSize
305
306
306{-
307{-
307{-# INLINE write #-}
308{-# INLINE write #-}
@@ -312,20 +313,20 @@ write = toHandleWith A.defaultChunkSize
312-- | Append a stream of arrays to a file.
313-- | Append a stream of arrays to a file.
313--
314--
314-- @since 0.7.0
315-- @since 0.7.0
315−{-# INLINE appendArrays #-}
316+{-# INLINE appendChunks #-}
316−appendArrays :: (MonadAsync m, MonadCatch m, Storable a)
317+appendChunks :: (MonadAsync m, MonadCatch m, Storable a)
317 => FilePath -> SerialT m (Array a) -> m ()
318 => FilePath -> SerialT m (Array a) -> m ()
318−appendArrays = writeArraysMode AppendMode
319+appendChunks = writeChunksMode AppendMode
319
320
320-- | Like 'append' but provides control over the write buffer. Output will
321-- | Like 'append' but provides control over the write buffer. Output will
321-- be written to the IO device as soon as we collect the specified number of
322-- be written to the IO device as soon as we collect the specified number of
322-- input elements.
323-- input elements.
323--
324--
324-- @since 0.7.0
325-- @since 0.7.0
325−{-# INLINE appendByChunks #-}
326+{-# INLINE appendRequestsOf #-}
326−appendByChunks :: (MonadAsync m, MonadCatch m)
327+appendRequestsOf :: (MonadAsync m, MonadCatch m)
327 => Int -> FilePath -> SerialT m Word8 -> m ()
328 => Int -> FilePath -> SerialT m Word8 -> m ()
328−appendByChunks n file xs = appendArrays file $ AS.arraysOf n xs
329+appendRequestsOf n file xs = appendChunks file $ AS.arraysOf n xs
329
330
330-- | Append a byte stream to a file. Combines the bytes in chunks of size up to
331-- | Append a byte stream to a file. Combines the bytes in chunks of size up to
331-- 'A.defaultChunkSize' before writing. If the file exists then the new data
332-- 'A.defaultChunkSize' before writing. If the file exists then the new data
@@ -335,7 +336,7 @@ appendByChunks n file xs = appendArrays file $ AS.arraysOf n xs
335-- @since 0.7.0
336-- @since 0.7.0
336{-# INLINE append #-}
337{-# INLINE append #-}
337append :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
338append :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
338−append = appendByChunks defaultChunkSize
339+append = appendRequestsOf defaultChunkSize
339
340
340{-
341{-
341-- | Like 'append' but the file is not locked for exclusive writes.
342-- | Like 'append' but the file is not locked for exclusive writes.
src/Streamly/Internal/FileSystem/Handle.hs+97−72
@@ -22,19 +22,19 @@ module Streamly.Internal.FileSystem.Handle
22 -- , readUtf8
22 -- , readUtf8
23 -- , readLines
23 -- , readLines
24 -- , readFrames
24 -- , readFrames
25− , readInChunksOf
25+ , readRequestsOf
26
26
27 , toStream
27 , toStream
28− , toStreamInChunksOf
28+ , toStreamRequestsOf
29
29
30 -- -- * Array Read
30 -- -- * Array Read
31 -- , readArrayUpto
31 -- , readArrayUpto
32 -- , readArrayOf
32 -- , readArrayOf
33− , readArraysOf
33+ , readChunks
34− , readArrays
34+ , readChunksRequestsOf
35
35
36− , toStreamArraysOf
36+ , toChunksRequestsOf
37− , toStreamArrays
37+ , toChunks
38
38
39 -- ** Write to Handle
39 -- ** Write to Handle
40 -- Byte stream write (Folds)
40 -- Byte stream write (Folds)
@@ -42,7 +42,7 @@ module Streamly.Internal.FileSystem.Handle
42 -- , writeUtf8
42 -- , writeUtf8
43 -- , writeUtf8ByLines
43 -- , writeUtf8ByLines
44 -- , writeByFrames
44 -- , writeByFrames
45− , writeInChunksOf
45+ , writeRequestsOf
46
46
47 -- Byte stream write (Streams)
47 -- Byte stream write (Streams)
48 , fromStream
48 , fromStream
@@ -50,8 +50,8 @@ module Streamly.Internal.FileSystem.Handle
50
50
51 -- -- * Array Write
51 -- -- * Array Write
52 , writeArray
52 , writeArray
53− , writeArrays
53+ , writeChunks
54− , writeArraysInChunksOf
54+ , writeChunksRequestsOf
55
55
56 -- -- * Array stream Write
56 -- -- * Array stream Write
57 , fromStreamArrays
57 , fromStreamArrays
@@ -63,18 +63,37 @@ module Streamly.Internal.FileSystem.Handle
63 -- include disks, files, memory devices and exclude terminals, pipes,
63 -- include disks, files, memory devices and exclude terminals, pipes,
64 -- sockets and fifos.
64 -- sockets and fifos.
65 --
65 --
66+ -- XXX need to decide whether to use readFromStepN style or readFromThenTo
67+ -- style. The latter is consistent with list enumeration. The former may be
68+ -- more unambiguous and it is easier and clearer to specify 0 elements.
69+ --
70+ -- We can also generate the request pattern using a funciton.
71+ --
66 -- , readIndex
72 -- , readIndex
67− -- , readSlice
73+ -- , readFrom -- read from a given position to the end of file
68− -- , readSliceRev
74+ -- , readFromRev -- read from a given position the beginning of file
69− -- , readAt -- read from a given position to th end of file
75+ -- , readTo -- read from beginning up to the given position
70− -- , readSliceArrayUpto
76+ -- , readToRev -- read from end to the given position in file
71− -- , readSliceArrayOf
77+ -- , readFromTo
78+ -- , readFromThenTo
79+
80+ -- , readChunksFrom
81+ -- , readChunksFromTo
82+ -- , readChunksFromToRequestsOf
83+ -- , readChunksFromThenToRequestsOf
72
84
73 -- , writeIndex
85 -- , writeIndex
74− -- , writeSlice
75− -- , writeSliceRev
76− -- , writeAt -- start writing at the given position
86+ -- , writeFrom -- start writing at the given position
77− -- , writeSliceArray
87+ -- , writeFromRev
88+ -- , writeTo -- write from beginning up to the given position
89+ -- , writeToRev
90+ -- , writeFromTo
91+ -- , writeFromThenTo
92+ --
93+ -- , writeChunksFrom
94+ -- , writeChunksFromTo
95+ -- , writeChunksFromToRequestsOf
96+ -- , writeChunksFromThenToRequestsOf
78 )
97 )
79where
98where
80
99
@@ -145,13 +164,13 @@ readArrayUpto size h = do
145-- Stream of Arrays IO
164-- Stream of Arrays IO
146-------------------------------------------------------------------------------
165-------------------------------------------------------------------------------
147
166
148−-- | @toStreamArraysOf size h@ reads a stream of arrays from file handle @h@.
167+-- | @toChunksRequestsOf size h@ reads a stream of arrays from file handle @h@.
149-- The maximum size of a single array is specified by @size@. The actual size
168-- The maximum size of a single array is specified by @size@. The actual size
150-- read may be less than or equal to @size@.
169-- read may be less than or equal to @size@.
151−{-# INLINABLE _toStreamArraysOf #-}
170+{-# INLINABLE _toChunksRequestsOf #-}
152−_toStreamArraysOf :: (IsStream t, MonadIO m)
171+_toChunksRequestsOf :: (IsStream t, MonadIO m)
153 => Int -> Handle -> t m (Array Word8)
172 => Int -> Handle -> t m (Array Word8)
154−_toStreamArraysOf size h = go
173+_toChunksRequestsOf size h = go
155 where
174 where
156 -- XXX use cons/nil instead
175 -- XXX use cons/nil instead
157 go = mkStream $ \_ yld _ stp -> do
176 go = mkStream $ \_ yld _ stp -> do
@@ -160,14 +179,14 @@ _toStreamArraysOf size h = go
160 then stp
179 then stp
161 else yld arr go
180 else yld arr go
162
181
163−-- | @toStreamArraysOf size handle@ reads a stream of arrays from the file
182+-- | @toChunksRequestsOf size handle@ reads a stream of arrays from the file
164-- handle @handle@. The maximum size of a single array is limited to @size@.
183-- handle @handle@. The maximum size of a single array is limited to @size@.
165-- The actual size read may be less than or equal to @size@.
184-- The actual size read may be less than or equal to @size@.
166--
185--
167-- @since 0.7.0
186-- @since 0.7.0
168−{-# INLINE_NORMAL toStreamArraysOf #-}
187+{-# INLINE_NORMAL toChunksRequestsOf #-}
169−toStreamArraysOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m (Array Word8)
188+toChunksRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m (Array Word8)
170−toStreamArraysOf size h = D.fromStreamD (D.Stream step ())
189+toChunksRequestsOf size h = D.fromStreamD (D.Stream step ())
171 where
190 where
172 {-# INLINE_LATE step #-}
191 {-# INLINE_LATE step #-}
173 step _ _ = do
192 step _ _ = do
@@ -179,12 +198,12 @@ toStreamArraysOf size h = D.fromStreamD (D.Stream step ())
179
198
180-- | Unfold the tuple @(size, handle)@ into a stream of 'Word8' arrays. The
199-- | Unfold the tuple @(size, handle)@ into a stream of 'Word8' arrays. The
181-- stream consists of arrays representing chunks of data read from the handle.
200-- stream consists of arrays representing chunks of data read from the handle.
182−-- The maximum size of a single array is limited to @size@.
201+-- The size of an array in the stream is less than or equal to @size@.
183--
202--
184-- @since 0.7.0
203-- @since 0.7.0
185−{-# INLINE_NORMAL readArraysOf #-}
204+{-# INLINE_NORMAL readChunksRequestsOf #-}
186−readArraysOf :: MonadIO m => Unfold m (Int, Handle) (Array Word8)
205+readChunksRequestsOf :: MonadIO m => Unfold m (Int, Handle) (Array Word8)
187−readArraysOf = Unfold step return
206+readChunksRequestsOf = Unfold step return
188 where
207 where
189 {-# INLINE_LATE step #-}
208 {-# INLINE_LATE step #-}
190 step (size, h) = do
209 step (size, h) = do
@@ -196,25 +215,28 @@ readArraysOf = Unfold step return
196
215
197-- XXX read 'Array a' instead of Word8
216-- XXX read 'Array a' instead of Word8
198--
217--
199−-- | @toStreamArrays handle@ reads a stream of arrays from the specified file
218+-- | @toChunks handle@ reads a stream of arrays from the specified file
200-- handle. The maximum size of a single array is limited to
219-- handle. The maximum size of a single array is limited to
201-- @defaultChunkSize@. The actual size read may be less than or equal to
220-- @defaultChunkSize@. The actual size read may be less than or equal to
202-- @defaultChunkSize@.
221-- @defaultChunkSize@.
203--
222--
204−-- > toStreamArrays = toStreamArraysOf defaultChunkSize
223+-- > toChunks = toChunksRequestsOf defaultChunkSize
205--
224--
206-- @since 0.7.0
225-- @since 0.7.0
207−{-# INLINE toStreamArrays #-}
226+{-# INLINE toChunks #-}
208−toStreamArrays :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
227+toChunks :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
209−toStreamArrays = toStreamArraysOf defaultChunkSize
228+toChunks = toChunksRequestsOf defaultChunkSize
210
229
211−-- | Unfolds a handle into a stream of 'Word8' arrays. The maximum size of a
230+-- | Unfolds a handle into a stream of 'Word8' arrays. Requests to the IO
212−-- single array is limited to @defaultChunkSize@.
231+-- device are performed using a buffer of size
232+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'. The
233+-- size of arrays in the resulting stream are therefore less than or equal to
234+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
213--
235--
214-- @since 0.7.0
236-- @since 0.7.0
215−{-# INLINE readArrays #-}
237+{-# INLINE readChunks #-}
216−readArrays :: MonadIO m => Unfold m Handle (Array Word8)
238+readChunks :: MonadIO m => Unfold m Handle (Array Word8)
217−readArrays = UF.supplyFirst readArraysOf defaultChunkSize
239+readChunks = UF.supplyFirst readChunksRequestsOf defaultChunkSize
218
240
219-------------------------------------------------------------------------------
241-------------------------------------------------------------------------------
220-- Read File to Stream
242-- Read File to Stream
@@ -224,40 +246,41 @@ readArrays = UF.supplyFirst readArraysOf defaultChunkSize
224-- read requests at the same time. For serial case we can use async IO. We can
246-- read requests at the same time. For serial case we can use async IO. We can
225-- also control the read throughput in mbps or IOPS.
247-- also control the read throughput in mbps or IOPS.
226
248
227−-- | @readInChunksOf@ unfolds @(chunksize, handle)@ into a byte stream, reads
249+-- | Unfolds the tuple @(chunksize, handle)@ into a byte stream, read requests
228−-- are performed in chunks of up to @chunkSize@.
250+-- to the IO device are performed using buffers of @chunkSize@.
229--
251--
230-- @since 0.7.0
252-- @since 0.7.0
231−{-# INLINE readInChunksOf #-}
253+{-# INLINE readRequestsOf #-}
232−readInChunksOf :: MonadIO m => Unfold m (Int, Handle) Word8
254+readRequestsOf :: MonadIO m => Unfold m (Int, Handle) Word8
233−readInChunksOf = UF.concat readArraysOf A.read
255+readRequestsOf = UF.concat readChunksRequestsOf A.read
234
256
235−-- | @toStreamInChunksOf chunkSize handle@ reads a byte stream from a file
257+-- | @toStreamRequestsOf chunkSize handle@ reads a byte stream from a file
236-- handle, reads are performed in chunks of up to @chunkSize@.
258-- handle, reads are performed in chunks of up to @chunkSize@.
237--
259--
238-- /Internal/
260-- /Internal/
239−{-# INLINE toStreamInChunksOf #-}
261+{-# INLINE toStreamRequestsOf #-}
240−toStreamInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
262+toStreamRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
241−toStreamInChunksOf chunkSize h = AS.concat $ toStreamArraysOf chunkSize h
263+toStreamRequestsOf chunkSize h = AS.concat $ toChunksRequestsOf chunkSize h
242
264
243-- TODO
265-- TODO
244-- Generate a stream of elements of the given type from a file 'Handle'.
266-- Generate a stream of elements of the given type from a file 'Handle'.
245-- read :: (IsStream t, MonadIO m, Storable a) => Handle -> t m a
267-- read :: (IsStream t, MonadIO m, Storable a) => Handle -> t m a
246--
268--
247−-- > read = 'readInChunksOf' A.defaultChunkSize
248−-- | Unfolds a file handle into a byte stream.
269+-- | Unfolds a file handle into a byte stream. IO requests to the device are
270+-- performed in sizes of
271+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
249--
272--
250-- @since 0.7.0
273-- @since 0.7.0
251{-# INLINE read #-}
274{-# INLINE read #-}
252read :: MonadIO m => Unfold m Handle Word8
275read :: MonadIO m => Unfold m Handle Word8
253−read = UF.supplyFirst readInChunksOf defaultChunkSize
276+read = UF.supplyFirst readRequestsOf defaultChunkSize
254
277
255-- | Generate a byte stream from a file 'Handle'.
278-- | Generate a byte stream from a file 'Handle'.
256--
279--
257-- /Internal/
280-- /Internal/
258{-# INLINE toStream #-}
281{-# INLINE toStream #-}
259toStream :: (IsStream t, MonadIO m) => Handle -> t m Word8
282toStream :: (IsStream t, MonadIO m) => Handle -> t m Word8
260−toStream = AS.concat . toStreamArrays
283+toStream = AS.concat . toChunks
261
284
262-------------------------------------------------------------------------------
285-------------------------------------------------------------------------------
263-- Writing
286-- Writing
@@ -316,10 +339,10 @@ fromStreamInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
316fromStreamInChunksOf n h m = fromStreamArrays h $ S.arraysOf n m
339fromStreamInChunksOf n h m = fromStreamArrays h $ S.arraysOf n m
317-- fromStreamInChunksOf n h m = fromStreamArrays h $ AS.arraysOf n m
340-- fromStreamInChunksOf n h m = fromStreamArrays h $ AS.arraysOf n m
318
341
319−-- > write = 'writeInChunksOf' A.defaultChunkSize
342+-- > write = 'writeRequestsOf' A.defaultChunkSize
320--
343--
321-- | Write a byte stream to a file handle. Accumulates the input in chunks of
344-- | Write a byte stream to a file handle. Accumulates the input in chunks of
322−-- up to 'A.defaultChunkSize' before writing.
345+-- up to 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before writing.
323--
346--
324-- NOTE: This may perform better than the 'write' fold, you can try this if you
347-- NOTE: This may perform better than the 'write' fold, you can try this if you
325-- need some extra perf boost.
348-- need some extra perf boost.
@@ -329,24 +352,25 @@ fromStreamInChunksOf n h m = fromStreamArrays h $ S.arraysOf n m
329fromStream :: MonadIO m => Handle -> SerialT m Word8 -> m ()
352fromStream :: MonadIO m => Handle -> SerialT m Word8 -> m ()
330fromStream = fromStreamInChunksOf defaultChunkSize
353fromStream = fromStreamInChunksOf defaultChunkSize
331
354
332−-- | Write a stream of arrays to a handle.
355+-- | Write a stream of arrays to a handle. Each array in the stream is written
356+-- to the device as a separate IO request.
333--
357--
334-- @since 0.7.0
358-- @since 0.7.0
335−{-# INLINE writeArrays #-}
359+{-# INLINE writeChunks #-}
336−writeArrays :: (MonadIO m, Storable a) => Handle -> Fold m (Array a) ()
360+writeChunks :: (MonadIO m, Storable a) => Handle -> Fold m (Array a) ()
337−writeArrays h = FL.drainBy (liftIO . writeArray h)
361+writeChunks h = FL.drainBy (liftIO . writeArray h)
338
362
339−-- | @writeArraysInChunksOf chunkSize handle@ writes a stream of arrays
363+-- | @writeChunksRequestsOf chunkSize handle@ writes a stream of arrays
340-- to @handle@ after coalescing the adjacent arrays in chunks of @chunkSize@.
364-- to @handle@ after coalescing the adjacent arrays in chunks of @chunkSize@.
341-- We never split an array, if a single array is bigger than the specified size
365-- We never split an array, if a single array is bigger than the specified size
342-- it emitted as it is. Multiple arrays are coalesed as long as the total size
366-- it emitted as it is. Multiple arrays are coalesed as long as the total size
343-- remains below the specified size.
367-- remains below the specified size.
344--
368--
345-- @since 0.7.0
369-- @since 0.7.0
346−{-# INLINE writeArraysInChunksOf #-}
370+{-# INLINE writeChunksRequestsOf #-}
347−writeArraysInChunksOf :: (MonadIO m, Storable a)
371+writeChunksRequestsOf :: (MonadIO m, Storable a)
348 => Int -> Handle -> Fold m (Array a) ()
372 => Int -> Handle -> Fold m (Array a) ()
349−writeArraysInChunksOf n h = lpackArraysChunksOf n (writeArrays h)
373+writeChunksRequestsOf n h = lpackArraysChunksOf n (writeChunks h)
350
374
351-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
375-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
352--
376--
@@ -356,24 +380,25 @@ writeArraysInChunksOf n h = lpackArraysChunksOf n (writeArrays h)
356-- do not want buffering to occur at GHC level as well. Same thing applies to
380-- do not want buffering to occur at GHC level as well. Same thing applies to
357-- writes as well.
381-- writes as well.
358
382
359−-- | @writeInChunksOf chunkSize handle@ writes the input stream to @handle@ in
383+-- | @writeRequestsOf reqSize handle@ writes the input stream to @handle@.
360−-- chunks of @chunkSize@. A write is performed to the IO device as soon as we
384+-- Bytes in the input stream are collected into a buffer until we have a chunk
361−-- collect the required input size.
385+-- of @reqSize@ and then written to the IO device.
362--
386--
363-- @since 0.7.0
387-- @since 0.7.0
364−{-# INLINE writeInChunksOf #-}
388+{-# INLINE writeRequestsOf #-}
365−writeInChunksOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
389+writeRequestsOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
366−writeInChunksOf n h = FL.lchunksOf n (writeNUnsafe n) (writeArrays h)
390+writeRequestsOf n h = FL.lchunksOf n (writeNUnsafe n) (writeChunks h)
367
391
368−-- > write = 'writeInChunksOf' A.defaultChunkSize
392+-- > write = 'writeRequestsOf' A.defaultChunkSize
369--
393--
370-- | Write a byte stream to a file handle. Accumulates the input in chunks of
394-- | Write a byte stream to a file handle. Accumulates the input in chunks of
371−-- up to 'A.defaultChunkSize' before writing.
395+-- up to 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before writing
396+-- to the IO device.
372--
397--
373-- @since 0.7.0
398-- @since 0.7.0
374{-# INLINE write #-}
399{-# INLINE write #-}
375write :: MonadIO m => Handle -> Fold m Word8 ()
400write :: MonadIO m => Handle -> Fold m Word8 ()
376−write = writeInChunksOf defaultChunkSize
401+write = writeRequestsOf defaultChunkSize
377
402
378{-
403{-
379{-# INLINE write #-}
404{-# INLINE write #-}
src/Streamly/Internal/Network/Inet/TCP.hs+24−24
@@ -53,20 +53,20 @@ module Streamly.Internal.Network.Inet.TCP
53 -- , readArrayUpto
53 -- , readArrayUpto
54 -- , readArrayOf
54 -- , readArrayOf
55
55
56− -- , readArraysUpto
56+ -- , readChunksUpto
57− -- , readArraysOf
57+ -- , readChunksOf
58− -- , readArrays
58+ -- , readChunks
59
59
60 -- *** Sink
60 -- *** Sink
61 , write
61 , write
62 -- , writeUtf8
62 -- , writeUtf8
63 -- , writeUtf8ByLines
63 -- , writeUtf8ByLines
64 -- , writeByFrames
64 -- , writeByFrames
65− -- , writeInChunksOf
65+ -- , writeRequestsOf
66
66
67 -- -- * Array Write
67 -- -- * Array Write
68 -- , writeArray
68 -- , writeArray
69− , writeArrays
69+ , writeChunks
70 {-
70 {-
71 -- ** Sink Servers
71 -- ** Sink Servers
72
72
@@ -283,7 +283,7 @@ withConnection addr port =
283{-# INLINE read #-}
283{-# INLINE read #-}
284read :: (MonadCatch m, MonadIO m)
284read :: (MonadCatch m, MonadIO m)
285 => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Word8
285 => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Word8
286−read = UF.concat (withServerAddr ISK.readArrays) A.read
286+read = UF.concat (withServerAddr ISK.readChunks) A.read
287
287
288-- | Read a stream from the supplied IPv4 host address and port number.
288-- | Read a stream from the supplied IPv4 host address and port number.
289--
289--
@@ -291,7 +291,7 @@ read = UF.concat (withServerAddr ISK.readArrays) A.read
291{-# INLINE toStream #-}
291{-# INLINE toStream #-}
292toStream :: (IsStream t, MonadCatch m, MonadIO m)
292toStream :: (IsStream t, MonadCatch m, MonadIO m)
293 => (Word8, Word8, Word8, Word8) -> PortNumber -> t m Word8
293 => (Word8, Word8, Word8, Word8) -> PortNumber -> t m Word8
294−toStream addr port = AS.concat $ withConnection addr port ISK.toStreamArrays
294+toStream addr port = AS.concat $ withConnection addr port ISK.toChunks
295
295
296-------------------------------------------------------------------------------
296-------------------------------------------------------------------------------
297-- Writing
297-- Writing
@@ -302,32 +302,32 @@ toStream addr port = AS.concat $ withConnection addr port ISK.toStreamArrays
302-- number.
302-- number.
303--
303--
304-- @since 0.7.0
304-- @since 0.7.0
305−{-# INLINE writeArrays #-}
305+{-# INLINE writeChunks #-}
306−writeArrays
306+writeChunks
307 :: (MonadCatch m, MonadAsync m)
307 :: (MonadCatch m, MonadAsync m)
308 => (Word8, Word8, Word8, Word8)
308 => (Word8, Word8, Word8, Word8)
309 -> PortNumber
309 -> PortNumber
310 -> SerialT m (Array Word8)
310 -> SerialT m (Array Word8)
311 -> m ()
311 -> m ()
312−writeArrays addr port xs =
312+writeChunks addr port xs =
313− S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.writeArrays sk xs)
313+ S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.writeChunks sk xs)
314-}
314-}
315
315
316-- | Write a stream of arrays to the supplied IPv4 host address and port
316-- | Write a stream of arrays to the supplied IPv4 host address and port
317-- number.
317-- number.
318--
318--
319-- @since 0.7.0
319-- @since 0.7.0
320−{-# INLINE writeArrays #-}
320+{-# INLINE writeChunks #-}
321−writeArrays
321+writeChunks
322 :: (MonadAsync m)
322 :: (MonadAsync m)
323 => (Word8, Word8, Word8, Word8)
323 => (Word8, Word8, Word8, Word8)
324 -> PortNumber
324 -> PortNumber
325 -> Fold m (Array Word8) ()
325 -> Fold m (Array Word8) ()
326−writeArrays addr port = Fold step initial extract
326+writeChunks addr port = Fold step initial extract
327 where
327 where
328 initial = do
328 initial = do
329 skt <- liftIO (connect addr port)
329 skt <- liftIO (connect addr port)
330− FL.initialize (SK.writeArrays skt)
330+ FL.initialize (SK.writeChunks skt)
331 step = FL.runStep
331 step = FL.runStep
332 extract (Fold _ initial1 extract1) = initial1 >>= extract1
332 extract (Fold _ initial1 extract1) = initial1 >>= extract1
333
333
@@ -337,15 +337,15 @@ writeArrays addr port = Fold step initial extract
337-- input elements.
337-- input elements.
338--
338--
339-- @since 0.7.0
339-- @since 0.7.0
340−{-# INLINE writeInChunksOf #-}
340+{-# INLINE writeRequestsOf #-}
341−writeInChunksOf
341+writeRequestsOf
342 :: (MonadCatch m, MonadAsync m)
342 :: (MonadCatch m, MonadAsync m)
343 => Int
343 => Int
344 -> (Word8, Word8, Word8, Word8)
344 -> (Word8, Word8, Word8, Word8)
345 -> PortNumber
345 -> PortNumber
346 -> SerialT m Word8
346 -> SerialT m Word8
347 -> m ()
347 -> m ()
348−writeInChunksOf n addr port m = writeArrays addr port $ AS.arraysOf n m
348+writeRequestsOf n addr port m = writeChunks addr port $ AS.arraysOf n m
349-}
349-}
350
350
351-- | Like 'write' but provides control over the write buffer. Output will
351-- | Like 'write' but provides control over the write buffer. Output will
@@ -353,15 +353,15 @@ writeInChunksOf n addr port m = writeArrays addr port $ AS.arraysOf n m
353-- input elements.
353-- input elements.
354--
354--
355-- @since 0.7.0
355-- @since 0.7.0
356−{-# INLINE writeInChunksOf #-}
356+{-# INLINE writeRequestsOf #-}
357−writeInChunksOf
357+writeRequestsOf
358 :: (MonadAsync m)
358 :: (MonadAsync m)
359 => Int
359 => Int
360 -> (Word8, Word8, Word8, Word8)
360 -> (Word8, Word8, Word8, Word8)
361 -> PortNumber
361 -> PortNumber
362 -> Fold m Word8 ()
362 -> Fold m Word8 ()
363−writeInChunksOf n addr port =
363+writeRequestsOf n addr port =
364− FL.lchunksOf n (writeNUnsafe n) (writeArrays addr port)
364+ FL.lchunksOf n (writeNUnsafe n) (writeChunks addr port)
365
365
366{-
366{-
367-- | Write a stream to the supplied IPv4 host address and port number.
367-- | Write a stream to the supplied IPv4 host address and port number.
@@ -370,7 +370,7 @@ writeInChunksOf n addr port =
370{-# INLINE write #-}
370{-# INLINE write #-}
371write :: (MonadCatch m, MonadAsync m)
371write :: (MonadCatch m, MonadAsync m)
372 => (Word8, Word8, Word8, Word8) -> PortNumber -> SerialT m Word8 -> m ()
372 => (Word8, Word8, Word8, Word8) -> PortNumber -> SerialT m Word8 -> m ()
373−write = writeInChunksOf defaultChunkSize
373+write = writeRequestsOf defaultChunkSize
374-}
374-}
375
375
376-- | Write a stream to the supplied IPv4 host address and port number.
376-- | Write a stream to the supplied IPv4 host address and port number.
@@ -379,4 +379,4 @@ write = writeInChunksOf defaultChunkSize
379{-# INLINE write #-}
379{-# INLINE write #-}
380write :: MonadAsync m
380write :: MonadAsync m
381 => (Word8, Word8, Word8, Word8) -> PortNumber -> Fold m Word8 ()
381 => (Word8, Word8, Word8, Word8) -> PortNumber -> Fold m Word8 ()
382−write = writeInChunksOf defaultChunkSize
382+write = writeRequestsOf defaultChunkSize
src/Streamly/Internal/Network/Socket.hs+64−56
@@ -29,6 +29,7 @@ module Streamly.Internal.Network.Socket
29
29
30 -- * Read from connection
30 -- * Read from connection
31 , read
31 , read
32+ , readRequestsOf
32 -- , readUtf8
33 -- , readUtf8
33 -- , readLines
34 -- , readLines
34 -- , readFrames
35 -- , readFrames
@@ -39,23 +40,23 @@ module Streamly.Internal.Network.Socket
39 -- , readArrayUpto
40 -- , readArrayUpto
40 -- , readArrayOf
41 -- , readArrayOf
41
42
42− -- , readArraysUpto
43+ -- , readChunksUpto
43− , readArraysOf
44+ , readChunksRequestsOf
44− , readArrays
45+ , readChunks
45
46
46− , toStreamArraysOf
47+ , toChunksRequestsOf
47− , toStreamArrays
48+ , toChunks
48
49
49 -- * Write to connection
50 -- * Write to connection
50 , write
51 , write
51 -- , writeUtf8
52 -- , writeUtf8
52 -- , writeUtf8ByLines
53 -- , writeUtf8ByLines
53 -- , writeByFrames
54 -- , writeByFrames
54− , writeInChunksOf
55+ , writeRequestsOf
55
56
56 -- -- * Array Write
57 -- -- * Array Write
57 , writeArray
58 , writeArray
58− , writeArrays
59+ , writeChunks
59
60
60 -- reading/writing datagrams
61 -- reading/writing datagrams
61 )
62 )
@@ -281,11 +282,11 @@ writeArray = writeArrayWith sendAll
281-- Stream of Arrays IO
282-- Stream of Arrays IO
282-------------------------------------------------------------------------------
283-------------------------------------------------------------------------------
283
284
284−{-# INLINABLE readArraysUptoWith #-}
285+{-# INLINABLE readChunksUptoWith #-}
285−readArraysUptoWith :: (IsStream t, MonadIO m)
286+readChunksUptoWith :: (IsStream t, MonadIO m)
286 => (Int -> h -> IO (Array Word8))
287 => (Int -> h -> IO (Array Word8))
287 -> Int -> h -> t m (Array Word8)
288 -> Int -> h -> t m (Array Word8)
288−readArraysUptoWith f size h = go
289+readChunksUptoWith f size h = go
289 where
290 where
290 -- XXX use cons/nil instead
291 -- XXX use cons/nil instead
291 go = mkStream $ \_ yld _ stp -> do
292 go = mkStream $ \_ yld _ stp -> do
@@ -294,33 +295,34 @@ readArraysUptoWith f size h = go
294 then stp
295 then stp
295 else yld arr go
296 else yld arr go
296
297
297−-- | @toStreamArraysOf size h@ reads a stream of arrays from file handle @h@.
298+-- | @toChunksRequestsOf size h@ reads a stream of arrays from file handle @h@.
298-- The maximum size of a single array is limited to @size@.
299-- The maximum size of a single array is limited to @size@.
299-- 'fromHandleArraysUpto' ignores the prevailing 'TextEncoding' and 'NewlineMode'
300-- 'fromHandleArraysUpto' ignores the prevailing 'TextEncoding' and 'NewlineMode'
300-- on the 'Handle'.
301-- on the 'Handle'.
301−{-# INLINABLE toStreamArraysOf #-}
302+{-# INLINABLE toChunksRequestsOf #-}
302−toStreamArraysOf :: (IsStream t, MonadIO m)
303+toChunksRequestsOf :: (IsStream t, MonadIO m)
303 => Int -> Socket -> t m (Array Word8)
304 => Int -> Socket -> t m (Array Word8)
304−toStreamArraysOf = readArraysUptoWith readArrayOf
305+toChunksRequestsOf = readChunksUptoWith readArrayOf
305
306
306-- XXX read 'Array a' instead of Word8
307-- XXX read 'Array a' instead of Word8
307--
308--
308−-- | @toStreamArrays h@ reads a stream of arrays from socket handle @h@.
309+-- | @toChunks h@ reads a stream of arrays from socket handle @h@.
309-- The maximum size of a single array is limited to @defaultChunkSize@.
310-- The maximum size of a single array is limited to @defaultChunkSize@.
310--
311--
311-- @since 0.7.0
312-- @since 0.7.0
312−{-# INLINE toStreamArrays #-}
313+{-# INLINE toChunks #-}
313−toStreamArrays :: (IsStream t, MonadIO m) => Socket -> t m (Array Word8)
314+toChunks :: (IsStream t, MonadIO m) => Socket -> t m (Array Word8)
314−toStreamArrays = toStreamArraysOf A.defaultChunkSize
315+toChunks = toChunksRequestsOf A.defaultChunkSize
315
316
316-- | Unfold the tuple @(size, socket)@ into a stream of 'Word8' arrays. The
317-- | Unfold the tuple @(size, socket)@ into a stream of 'Word8' arrays. The
317-- stream consists of arrays representing chunks of data read from the socket.
318-- stream consists of arrays representing chunks of data read from the socket.
318−-- The maximum size of a single array is limited to @size@.
319+-- The size of an array in the resulting stream is less than or equal to
320+-- @size@.
319--
321--
320-- @since 0.7.0
322-- @since 0.7.0
321−{-# INLINE_NORMAL readArraysOf #-}
323+{-# INLINE_NORMAL readChunksRequestsOf #-}
322−readArraysOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8)
324+readChunksRequestsOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8)
323−readArraysOf = Unfold step return
325+readChunksRequestsOf = Unfold step return
324 where
326 where
325 {-# INLINE_LATE step #-}
327 {-# INLINE_LATE step #-}
326 step (size, h) = do
328 step (size, h) = do
@@ -330,13 +332,16 @@ readArraysOf = Unfold step return
330 0 -> D.Stop
332 0 -> D.Stop
331 _ -> D.Yield arr (size, h)
333 _ -> D.Yield arr (size, h)
332
334
333−-- | Unfolds a socket into a stream of 'Word8' arrays. The maximum size of a
335+-- | Unfolds a socket into a stream of 'Word8' arrays. Requests to the socket
334−-- single array is limited to @defaultChunkSize@.
336+-- are performed using a buffer of size
337+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'. The
338+-- size of arrays in the resulting stream are therefore less than or equal to
339+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
335--
340--
336-- @since 0.7.0
341-- @since 0.7.0
337−{-# INLINE readArrays #-}
342+{-# INLINE readChunks #-}
338−readArrays :: MonadIO m => Unfold m Socket (Array Word8)
343+readChunks :: MonadIO m => Unfold m Socket (Array Word8)
339−readArrays = UF.supplyFirst readArraysOf A.defaultChunkSize
344+readChunks = UF.supplyFirst readChunksRequestsOf A.defaultChunkSize
340
345
341-------------------------------------------------------------------------------
346-------------------------------------------------------------------------------
342-- Read File to Stream
347-- Read File to Stream
@@ -347,13 +352,13 @@ readArrays = UF.supplyFirst readArraysOf A.defaultChunkSize
347-- also control the read throughput in mbps or IOPS.
352-- also control the read throughput in mbps or IOPS.
348
353
349{-
354{-
350−-- | @readInChunksOf chunkSize handle@ reads a byte stream from a file
355+-- | @readRequestsOf chunkSize handle@ reads a byte stream from a file
351-- handle, reads are performed in chunks of up to @chunkSize@. The stream ends
356-- handle, reads are performed in chunks of up to @chunkSize@. The stream ends
352-- as soon as EOF is encountered.
357-- as soon as EOF is encountered.
353--
358--
354−{-# INLINE readInChunksOf #-}
359+{-# INLINE readRequestsOf #-}
355−readInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
360+readRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
356−readInChunksOf chunkSize h = A.flattenArrays $ readArraysUpto chunkSize h
361+readRequestsOf chunkSize h = A.flattenArrays $ readChunksUpto chunkSize h
357-}
362-}
358
363
359-- TODO
364-- TODO
@@ -366,22 +371,24 @@ readInChunksOf chunkSize h = A.flattenArrays $ readArraysUpto chunkSize h
366-- @since 0.7.0
371-- @since 0.7.0
367{-# INLINE toStream #-}
372{-# INLINE toStream #-}
368toStream :: (IsStream t, MonadIO m) => Socket -> t m Word8
373toStream :: (IsStream t, MonadIO m) => Socket -> t m Word8
369−toStream = AS.concat . toStreamArrays
374+toStream = AS.concat . toChunks
370
375
371−-- | @readInChunksOf@ unfolds @(bufsize, socket)@ into a byte stream, reads
376+-- | Unfolds the tuple @(chunksize, socket)@ into a byte stream, read requests
372−-- are performed in buffers of up to @bufsize@.
377+-- to the socket are performed using buffers of @chunkSize@.
373--
378--
374-- @since 0.7.0
379-- @since 0.7.0
375−{-# INLINE readInChunksOf #-}
380+{-# INLINE readRequestsOf #-}
376−readInChunksOf :: MonadIO m => Unfold m (Int, Socket) Word8
381+readRequestsOf :: MonadIO m => Unfold m (Int, Socket) Word8
377−readInChunksOf = UF.concat readArraysOf A.read
382+readRequestsOf = UF.concat readChunksRequestsOf A.read
378
383
379−-- | Unfolds a 'Socket' into a byte stream.
384+-- | Unfolds a 'Socket' into a byte stream. IO requests to the socket are
385+-- performed in sizes of
386+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
380--
387--
381-- @since 0.7.0
388-- @since 0.7.0
382{-# INLINE read #-}
389{-# INLINE read #-}
383read :: MonadIO m => Unfold m Socket Word8
390read :: MonadIO m => Unfold m Socket Word8
384−read = UF.supplyFirst readInChunksOf A.defaultChunkSize
391+read = UF.supplyFirst readRequestsOf A.defaultChunkSize
385
392
386-------------------------------------------------------------------------------
393-------------------------------------------------------------------------------
387-- Writing
394-- Writing
@@ -390,17 +397,18 @@ read = UF.supplyFirst readInChunksOf A.defaultChunkSize
390-- | Write a stream of arrays to a handle.
397-- | Write a stream of arrays to a handle.
391--
398--
392-- @since 0.7.0
399-- @since 0.7.0
393−{-# INLINE writeArraysS #-}
400+{-# INLINE writeChunksS #-}
394−writeArraysS :: (MonadIO m, Storable a)
401+writeChunksS :: (MonadIO m, Storable a)
395 => Socket -> SerialT m (Array a) -> m ()
402 => Socket -> SerialT m (Array a) -> m ()
396−writeArraysS h m = S.mapM_ (liftIO . writeArray h) m
403+writeChunksS h m = S.mapM_ (liftIO . writeArray h) m
397
404
398−-- | Write a stream of arrays to a socket.
405+-- | Write a stream of arrays to a socket. Each array in the stream is written
406+-- to the socket as a separate IO request.
399--
407--
400-- @since 0.7.0
408-- @since 0.7.0
401−{-# INLINE writeArrays #-}
409+{-# INLINE writeChunks #-}
402−writeArrays :: (MonadIO m, Storable a) => Socket -> Fold m (Array a) ()
410+writeChunks :: (MonadIO m, Storable a) => Socket -> Fold m (Array a) ()
403−writeArrays h = FL.drainBy (liftIO . writeArray h)
411+writeChunks h = FL.drainBy (liftIO . writeArray h)
404
412
405-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
413-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
406--
414--
@@ -415,19 +423,19 @@ writeArrays h = FL.drainBy (liftIO . writeArray h)
415-- input elements.
423-- input elements.
416--
424--
417-- @since 0.7.0
425-- @since 0.7.0
418−{-# INLINE writeInChunksOfS #-}
426+{-# INLINE writeRequestsOfS #-}
419−writeInChunksOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
427+writeRequestsOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
420−writeInChunksOfS n h m = writeArraysS h $ AS.arraysOf n m
428+writeRequestsOfS n h m = writeChunksS h $ AS.arraysOf n m
421
429
422-- | Write a byte stream to a socket. Accumulates the input in chunks of
430-- | Write a byte stream to a socket. Accumulates the input in chunks of
423-- specified number of bytes before writing.
431-- specified number of bytes before writing.
424--
432--
425-- @since 0.7.0
433-- @since 0.7.0
426−{-# INLINE writeInChunksOf #-}
434+{-# INLINE writeRequestsOf #-}
427−writeInChunksOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
435+writeRequestsOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
428−writeInChunksOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeArrays h)
436+writeRequestsOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeChunks h)
429
437
430−-- > write = 'writeInChunksOf' A.defaultChunkSize
438+-- > write = 'writeRequestsOf' A.defaultChunkSize
431--
439--
432-- | Write a byte stream to a file handle. Combines the bytes in chunks of size
440-- | Write a byte stream to a file handle. Combines the bytes in chunks of size
433-- up to 'A.defaultChunkSize' before writing. Note that the write behavior
441-- up to 'A.defaultChunkSize' before writing. Note that the write behavior
@@ -436,19 +444,19 @@ writeInChunksOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeArrays h)
436-- @since 0.7.0
444-- @since 0.7.0
437{-# INLINE _writeS #-}
445{-# INLINE _writeS #-}
438_writeS :: MonadIO m => Socket -> SerialT m Word8 -> m ()
446_writeS :: MonadIO m => Socket -> SerialT m Word8 -> m ()
439−_writeS = writeInChunksOfS A.defaultChunkSize
447+_writeS = writeRequestsOfS A.defaultChunkSize
440
448
441-- | Write a byte stream to a socket. Accumulates the input in chunks of
449-- | Write a byte stream to a socket. Accumulates the input in chunks of
442-- up to 'A.defaultChunkSize' bytes before writing.
450-- up to 'A.defaultChunkSize' bytes before writing.
443--
451--
444-- @
452-- @
445−-- write = 'writeInChunksOf' 'A.defaultChunkSize'
453+-- write = 'writeRequestsOf' 'A.defaultChunkSize'
446-- @
454-- @
447--
455--
448-- @since 0.7.0
456-- @since 0.7.0
449{-# INLINE write #-}
457{-# INLINE write #-}
450write :: MonadIO m => Socket -> Fold m Word8 ()
458write :: MonadIO m => Socket -> Fold m Word8 ()
451−write = writeInChunksOf A.defaultChunkSize
459+write = writeRequestsOf A.defaultChunkSize
452
460
453{-
461{-
454{-# INLINE write #-}
462{-# INLINE write #-}
src/Streamly/Memory/Array.hs+19−37
@@ -16,48 +16,30 @@
16-- Stability : experimental
16-- Stability : experimental
17-- Portability : GHC
17-- Portability : GHC
18--
18--
19−-- This module provides immutable arrays suitable for storage and random
19+-- This module provides immutable arrays in pinned memory (non GC memory)
20−-- access. Once created an array cannot be mutated without copying. Arrays in
20+-- suitable for long lived data storage, random access and for interfacing with
21−-- this module are chunks of memory that hold a sequence of 'Storable' values
21+-- the operating system.
22−-- of a given type. They are designed to store serializable data, they cannot
23−-- store non-serializable data like functions, this is reflected by the
24−-- 'Storable' constraint. For efficient buffering of data, arrays use pinned
25−-- memory and therefore can hold arbitrary number of elements with a single
26−-- movable pointer visible to GC, therefore, adding no pressure to GC.
27−-- Moreover, pinned memory allows communication with foreign consumers and
28−-- producers (e.g. file or network IO) without copying the data.
29--
22--
30−-- By design, there are no array transformation operations provided in this
23+-- Arrays in this module are chunks of pinned memory that hold a sequence of
31−-- module, only conversion to and from stream is provided. Arrays can be
24+-- 'Storable' values of a given type, they cannot store non-serializable data
32−-- operated upon /efficiently/ by converting them into a stream, applying the
25+-- like functions. Once created an array cannot be modified. Pinned memory
33−-- desired stream transformations from "Streamly.Prelude" and then converting
26+-- allows efficient buffering of long lived data without adding any impact to
34−-- it back to an array.
27+-- GC. One array is just one pointer visible to GC and it does not have to
28+-- copied across generations. Moreover, pinned memory allows communication
29+-- with foreign consumers and producers (e.g. file or network IO) without
30+-- copying the data.
35--
31--
36−-- This module is designed to be imported qualified:
32+-- = Programmer Notes
37--
33--
38−-- > import qualified Streamly.Array as A
34+-- To apply a transformation to an array use 'read' to unfold the array into a
39−
35+-- stream, apply a transformation on the stream and then use 'write' to fold it
40−-- To summarize:
36+-- back to an array.
41--
37--
42−-- Arrays are finite and fixed in size
38+-- This module is designed to be imported qualified:
43−-- provide /O(1)/ access to elements
44−-- store only data and not functions
45−-- provide efficient IO interfacing
46--
39--
47−-- 'Foldable' instance is not provided because the implementation would be much
40+-- > import qualified Streamly.Array as A
48−-- less efficient compared to folding via streams. 'Semigroup' and 'Monoid'
49−-- instances are deliberately not provided to avoid misuse; concatenating
50−-- arrays using binary operations can be highly inefficient. Instead, use
51−-- 'Streamly.Memory.Array.Stream.toArray' to concatenate N arrays at once.
52--
41--
53−-- Each array is one pointer visible to the GC. Too many small arrays (e.g.
42+-- For experimental APIs see "Streamly.Internal.Memory.Array".
54−-- single byte) are only as good as holding those elements in a Haskell list.
55−-- However, small arrays can be compacted into large ones to reduce the
56−-- overhead. To hold 32GB memory in 32k sized buffers we need 1 million arrays
57−-- if we use one array for each chunk. This is still significant to add
58−-- pressure to GC. However, we can create arrays of arrays (trees) to scale to
59−-- arbitrarily large amounts of memory but still using small chunks of
60−-- contiguous memory.
61
43
62module Streamly.Memory.Array
44module Streamly.Memory.Array
63 (
45 (
@@ -68,7 +50,7 @@ module Streamly.Memory.Array
68 -- * Arrays
50 -- * Arrays
69 -- ** Construction
51 -- ** Construction
70 -- | When performance matters, the fastest way to generate an array is
52 -- | When performance matters, the fastest way to generate an array is
71− -- 'writeN'. For regular use, 'IsList' and 'IsString' instances can be
53+ -- 'writeN'. 'IsList' and 'IsString' instances can be
72 -- used to conveniently construct arrays from literal values.
54 -- used to conveniently construct arrays from literal values.
73 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
55 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
74 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
56 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
src/Streamly/Network/Socket.hs+13−27
@@ -15,15 +15,18 @@
15-- for connected sockets do not need to explicitly specify the remote endpoint.
15-- for connected sockets do not need to explicitly specify the remote endpoint.
16-- APIs for unconnected sockets need to explicitly specify the remote endpoint.
16-- APIs for unconnected sockets need to explicitly specify the remote endpoint.
17--
17--
18+-- = Programmer Notes
19+--
18-- Read IO requests to connected stream sockets are performed in chunks of
20-- Read IO requests to connected stream sockets are performed in chunks of
19−-- 32KiB, this is referred to as @defaultChunkSize@ in the documentation. One
21+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'. Unless specified
20−-- IO request may or may not read the full chunk. Unless specified otherwise
21−-- in the API, writes are collected into chunks of @defaultChunkSize@ before
22+-- otherwise in the API, writes are collected into chunks of
23+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before they are
22−-- they are written to the socket. APIs are provided to control the chunking
24+-- written to the socket. APIs are provided to control the chunking behavior.
23−-- and framing behavior.
24--
25--
25-- > import qualified Streamly.Network.Socket as SK
26-- > import qualified Streamly.Network.Socket as SK
26--
27--
28+-- For additional, experimental APIs take a look at
29+-- "Streamly.Internal.Network.Socket" module.
27
30
28-- By design, connected socket IO APIs are similar to
31-- By design, connected socket IO APIs are similar to
29-- "Streamly.Memory.Array" read write APIs. They are almost identical to the
32-- "Streamly.Memory.Array" read write APIs. They are almost identical to the
@@ -39,31 +42,14 @@ module Streamly.Network.Socket
39
42
40 -- * Read
43 -- * Read
41 , read
44 , read
42− -- , readUtf8
45+ , readRequestsOf
43− -- , readLines
46+ , readChunks
44− -- , readFrames
47+ , readChunksRequestsOf
45− -- , readByChunks
46−
47− -- -- * Array Read
48− -- , readArrayUpto
49− -- , readArrayOf
50−
51− -- , readArraysUpto
52− , readArraysOf
53− -- , readArrays
54
48
55 -- * Write
49 -- * Write
56 , write
50 , write
57− -- , writeUtf8
51+ , writeRequestsOf
58− -- , writeUtf8ByLines
52+ , writeChunks
59− -- , writeByFrames
60− -- , writeInChunksOf
61−
62− -- -- * Array Write
63− -- , writeArray
64− , writeArrays
65−
66− -- reading/writing datagrams
67 )
53 )
68where
54where
69
55