on master help sign in
Rename some IO APIs and update documentation
commit9bf84d4d37754da0a647df2e63531a9aa591ddec authorHarendra Kumar <harendra.kumar@gmail.com> dateWed 6 Nov 2019, 01:30 (7 years ago) parent10bb2fb
14 files changed+325−325
examples/EchoServer.hs+5−2 examples/FileIOExamples.hs+9−3 examples/FromFileClient.hs+2−2 examples/HandleIO.hs+10−6 examples/WordCount.hs+1−1 src/Streamly/Benchmark/FileIO/Array.hs+20−20 src/Streamly/Benchmark/FileIO/Stream.hs+2−2 src/Streamly/FileSystem/Handle.hs+22−37 src/Streamly/Internal/FileSystem/File.hs+37−36 src/Streamly/Internal/FileSystem/Handle.hs+97−72 src/Streamly/Internal/Network/Inet/TCP.hs+24−24 src/Streamly/Internal/Network/Socket.hs+64−56 src/Streamly/Memory/Array.hs+19−37 src/Streamly/Network/Socket.hs+13−27
examples/EchoServer.hs+5−2
@@ -12,5 +12,8 @@ main :: IO ()
1212main = S.drain
1313 $ parallely $ S.mapM (useWith echo)
1414 $ serially $ S.unfold TCP.acceptOnPort 8090
15− where echo sk = S.fold (writeArrays sk) $ S.unfold readArraysOf (32768, sk)
16− useWith f sk = finally (liftIO (Net.close sk)) (f sk)
15+ where
16+ echo sk =
17+ S.fold (writeChunks sk)
18+ $ S.unfold readChunksRequestsOf (32768, 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)
88import System.Environment (getArgs)
99
1010cat :: 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
1214
1315cp :: 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
1519
1620append :: 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
1824
1925ord' :: Num a => Char -> a
2026ord' = (fromIntegral . ord)
examples/FromFileClient.hs+2−2
@@ -16,6 +16,6 @@ main :: IO ()
1616main =
1717 let sendFile file =
1818 withFile file ReadMode $ \src ->
19− S.fold (TCP.writeArrays (127, 0, 0, 1) 8090)
20− $ IFH.toStreamArrays src
19+ S.fold (TCP.writeChunks (127, 0, 0, 1) 8090)
20+ $ IFH.toChunks src
2121 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
66import qualified Streamly.FileSystem.Handle as FH
77import qualified System.IO as FH
88-- import qualified Streamly.FileSystem.FD as FH
9−-- import qualified Streamly.String as SS
9+-- import qualified Streamly.Data.Unicode.Stream as US
1010
1111import Data.Char (ord)
1212import System.Environment (getArgs)
1313import System.IO (IOMode(..), hSeek, SeekMode(..))
1414
1515cat :: 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
1719-- byte stream version
1820-- cat src = S.fold (FH.write FH.stdout) $ FH.read src
1921
2022cp :: 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
2226-- byte stream version
2327-- cp src dst = S.fold (FH.write dst) $ FH.read src
2428
@@ -28,12 +32,12 @@ ord' = (fromIntegral . ord)
2832wcl :: FH.Handle -> IO ()
2933wcl src = print =<< (S.length
3034 $ AS.splitOn 10
31− $ IFH.toStreamArrays src)
35+ $ IFH.toChunks src)
3236{-
3337-- Char stream version
3438wcl src = print =<< (S.length
35− $ flip SS.foldLines FL.drain
36− $ SS.decodeChar8
39+ $ flip US.lines FL.drain
40+ $ US.decodeLatin1
3741 $ FH.read src)
3842-}
3943
examples/WordCount.hs+1−1
@@ -608,7 +608,7 @@ wc_mwl_parallel src n = do
608608 $ S.aheadly
609609 $ S.maxThreads numCapabilities
610610 $ S.mapM (countArray)
611− $ S.unfold FH.readArraysOf (n, src)
611+ $ S.unfold FH.readChunksRequestsOf (n, src)
612612
613613-------------------------------------------------------------------------------
614614-- Main
src/Streamly/Benchmark/FileIO/Array.hs+20−20
@@ -63,7 +63,7 @@ import Test.Inspection
6363{-# INLINE last #-}
6464last :: Handle -> IO (Maybe Word8)
6565last inh = do
66− let s = IFH.toStreamArrays inh
66+ let s = IFH.toChunks inh
6767 larr <- S.last s
6868 return $ case larr of
6969 Nothing -> Nothing
@@ -78,7 +78,7 @@ inspect $ 'last `hasNoType` ''Step
7878{-# INLINE countBytes #-}
7979countBytes :: Handle -> IO Int
8080countBytes inh =
81− let s = IFH.toStreamArrays inh
81+ let s = IFH.toChunks inh
8282 in S.sum (S.map A.length s)
8383
8484#ifdef INSPECTION
@@ -89,7 +89,7 @@ inspect $ 'countBytes `hasNoType` ''Step
8989-- | Count the number of lines in a file.
9090{-# INLINE countLines #-}
9191countLines :: Handle -> IO Int
92−countLines = S.length . AS.splitOnSuffix 10 . IFH.toStreamArrays
92+countLines = S.length . AS.splitOnSuffix 10 . IFH.toChunks
9393
9494#ifdef INSPECTION
9595inspect $ hasNoTypeClasses 'countLines
@@ -100,7 +100,7 @@ inspect $ 'countLines `hasNoType` ''Step
100100-- | Count the number of lines in a file.
101101{-# INLINE countWords #-}
102102countWords :: Handle -> IO Int
103−countWords = S.length . AS.splitOn 32 . IFH.toStreamArrays
103+countWords = S.length . AS.splitOn 32 . IFH.toChunks
104104
105105#ifdef INSPECTION
106106inspect $ hasNoTypeClasses 'countWords
@@ -112,7 +112,7 @@ inspect $ 'countWords `hasNoType` ''Step
112112sumBytes :: Handle -> IO Word8
113113sumBytes inh = do
114114 let foldlArr' f z = runIdentity . S.foldl' f z . IA.toStream
115− let s = IFH.toStreamArrays inh
115+ let s = IFH.toChunks inh
116116 S.foldl' (\acc arr -> acc + foldlArr' (+) 0 arr) 0 s
117117
118118#ifdef INSPECTION
@@ -124,7 +124,7 @@ inspect $ 'sumBytes `hasNoType` ''Step
124124{-# INLINE cat #-}
125125cat :: Handle -> Handle -> IO ()
126126cat devNull inh =
127− S.fold (IFH.writeArrays devNull) $ IFH.toStreamArraysOf (256*1024) inh
127+ S.fold (IFH.writeChunks devNull) $ IFH.toChunksRequestsOf (256*1024) inh
128128
129129#ifdef INSPECTION
130130inspect $ hasNoTypeClasses 'cat
@@ -136,8 +136,8 @@ inspect $ 'cat `hasNoType` ''Step
136136catBracket :: Handle -> Handle -> IO ()
137137catBracket devNull inh =
138138 let readEx = IUF.bracket return (\_ -> hClose inh)
139− (IUF.supplyFirst FH.readArraysOf (256*1024))
140− in IUF.fold readEx (IFH.writeArrays devNull) inh
139+ (IUF.supplyFirst FH.readChunksRequestsOf (256*1024))
140+ in IUF.fold readEx (IFH.writeChunks devNull) inh
141141
142142#ifdef INSPECTION
143143inspect $ hasNoTypeClasses 'catBracket
@@ -149,8 +149,8 @@ inspect $ hasNoTypeClasses 'catBracket
149149catBracketStream :: Handle -> Handle -> IO ()
150150catBracketStream devNull inh =
151151 let readEx = S.bracket (return ()) (\_ -> hClose inh)
152− (\_ -> IFH.toStreamArraysOf (256*1024) inh)
153− in S.fold (IFH.writeArrays devNull) $ readEx
152+ (\_ -> IFH.toChunksRequestsOf (256*1024) inh)
153+ in S.fold (IFH.writeChunks devNull) $ readEx
154154
155155#ifdef INSPECTION
156156inspect $ hasNoTypeClasses 'catBracketStream
@@ -162,8 +162,8 @@ inspect $ hasNoTypeClasses 'catBracketStream
162162catOnException :: Handle -> Handle -> IO ()
163163catOnException devNull inh =
164164 let readEx = IUF.onException (\_ -> hClose inh)
165− (IUF.supplyFirst FH.readArraysOf (256*1024))
166− in IUF.fold readEx (IFH.writeArrays devNull) inh
165+ (IUF.supplyFirst FH.readChunksRequestsOf (256*1024))
166+ in IUF.fold readEx (IFH.writeChunks devNull) inh
167167
168168#ifdef INSPECTION
169169inspect $ hasNoTypeClasses 'catOnException
@@ -174,8 +174,8 @@ inspect $ hasNoTypeClasses 'catOnException
174174{-# INLINE copy #-}
175175copy :: Handle -> Handle -> IO ()
176176copy inh outh =
177− let s = IFH.toStreamArrays inh
178− in S.fold (IFH.writeArrays outh) s
177+ let s = IFH.toChunks inh
178+ in S.fold (IFH.writeChunks outh) s
179179
180180#ifdef INSPECTION
181181inspect $ hasNoTypeClasses 'copy
@@ -186,10 +186,10 @@ inspect $ 'copy `hasNoType` ''Step
186186{-# INLINE linesUnlinesCopy #-}
187187linesUnlinesCopy :: Handle -> Handle -> IO ()
188188linesUnlinesCopy inh outh =
189− S.fold (IFH.writeInChunksOf (1024*1024) outh)
189+ S.fold (IFH.writeRequestsOf (1024*1024) outh)
190190 $ AS.interposeSuffix 10
191191 $ AS.splitOnSuffix 10
192− $ IFH.toStreamArraysOf (1024*1024) inh
192+ $ IFH.toChunksRequestsOf (1024*1024) inh
193193
194194#ifdef INSPECTION
195195inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
@@ -200,11 +200,11 @@ inspect $ hasNoTypeClassesExcept 'linesUnlinesCopy [''Storable]
200200{-# INLINE wordsUnwordsCopy #-}
201201wordsUnwordsCopy :: Handle -> Handle -> IO ()
202202wordsUnwordsCopy inh outh =
203− S.fold (IFH.writeInChunksOf (1024*1024) outh)
203+ S.fold (IFH.writeRequestsOf (1024*1024) outh)
204204 $ AS.interpose 32
205205 -- XXX this is not correct word splitting combinator
206206 $ AS.splitOn 32
207− $ IFH.toStreamArraysOf (1024*1024) inh
207+ $ IFH.toChunksRequestsOf (1024*1024) inh
208208
209209#ifdef INSPECTION
210210inspect $ hasNoTypeClassesExcept 'wordsUnwordsCopy [''Storable]
@@ -216,7 +216,7 @@ decodeUtf8Lenient :: Handle -> IO ()
216216decodeUtf8Lenient inh =
217217 S.drain
218218 $ IUS.decodeUtf8ArraysLenient
219− $ IFH.toStreamArraysOf (1024*1024) inh
219+ $ IFH.toChunksRequestsOf (1024*1024) inh
220220
221221#ifdef INSPECTION
222222inspect $ hasNoTypeClasses 'decodeUtf8Lenient
@@ -232,7 +232,7 @@ copyCodecUtf8Lenient inh outh =
232232 S.fold (FH.write outh)
233233 $ SS.encodeUtf8
234234 $ IUS.decodeUtf8ArraysLenient
235− $ IFH.toStreamArraysOf (1024*1024) inh
235+ $ IFH.toChunksRequestsOf (1024*1024) inh
236236
237237#ifdef INSPECTION
238238inspect $ hasNoTypeClasses 'copyCodecUtf8Lenient
src/Streamly/Benchmark/FileIO/Stream.hs+2−2
@@ -153,7 +153,7 @@ countLinesU inh =
153153 S.length
154154 $ IUS.lines FL.drain
155155 $ SS.decodeLatin1
156− $ S.concatUnfold A.read (IFH.toStreamArrays inh)
156+ $ S.concatUnfold A.read (IFH.toChunks inh)
157157
158158#ifdef INSPECTION
159159inspect $ hasNoTypeClasses 'countLinesU
@@ -600,7 +600,7 @@ splitOnSeqUtf8 :: String -> Handle -> IO Int
600600splitOnSeqUtf8 str inh =
601601 (S.length $ IP.splitOnSeq (A.fromList str) FL.drain
602602 $ IUS.decodeUtf8ArraysLenient
603− $ IFH.toStreamArrays inh) -- >>= print
603+ $ IFH.toChunks inh) -- >>= print
604604
605605-- | Split on suffix sequence.
606606{-# INLINE splitOnSuffixSeq #-}
src/Streamly/FileSystem/Handle.hs+22−37
@@ -25,8 +25,20 @@
2525-- 'NewLineMode', and 'Buffering' options of the underlying handle provided by
2626-- GHC are not needed and ignored.
2727--
28+-- = Programmer Notes
29+--
2830-- > import qualified Streamly.FileSystem.Handle as FH
2931--
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.
3042
3143-- IO APIs are divided into two categories, sequential streaming IO APIs and
3244-- random access IO APIs.
@@ -37,12 +49,14 @@ module Streamly.FileSystem.Handle
3749 -- | Stream data to or from a file or device sequentially. When reading,
3850 -- the stream is lazy and generated on-demand as the consumer consumes it.
3951 -- 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
4154 -- documentation. One IO request may or may not read the full
4255 -- chunk. If the whole stream is not consumed, it is possible that we may
4356 -- read slightly more from the IO device than what the consumer needed.
4457 -- Unless specified otherwise in the API, writes are collected into chunks
45− -- of @defaultChunkSize@ before they are written to the IO device.
58+ -- of 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before they
59+ -- are written to the IO device.
4660
4761 -- Streaming APIs work for all kind of devices, seekable or non-seekable;
4862 -- including disks, files, memory devices, terminals, pipes, sockets and
@@ -57,49 +71,20 @@ module Streamly.FileSystem.Handle
5771 -- position of the file handle. The stream ends as soon as EOF is
5872 -- encountered.
5973
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.
6274 read
63− -- , readUtf8
64− -- , readLines
65− -- , readFrames
66− , readInChunksOf
67− , readArraysOf
68− , readArrays
75+ , readRequestsOf
76+ , readChunks
77+ , readChunksRequestsOf
6978
7079 -- ** Write to Handle
7180 -- | 'TextEncoding', 'NewLineMode', and 'Buffering' options of the
7281 -- underlying handle are ignored. The write occurs from the current seek
7382 -- position of the file handle. The write behavior depends on the 'IOMode'
7483 -- 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
9784
98− -- , writeIndex
99− -- , writeSlice
100− -- , writeSliceRev
101− -- , writeAt -- start writing at the given position
102− -- , writeSliceArray
85+ , write
86+ , writeRequestsOf
87+ , writeChunks
10388 )
10489where
10590
src/Streamly/Internal/FileSystem/File.hs+37−36
@@ -63,27 +63,27 @@ module Streamly.Internal.FileSystem.File
6363 -- -- * Array Read
6464 -- , readArrayOf
6565
66− , toStreamArraysOf
67− -- , toStreamArraysOf
68− , toStreamArrays
66+ , toChunksRequestsOf
67+ -- , toChunksRequestsOf
68+ , toChunks
6969
7070 -- ** Write To File
7171 , write
7272 -- , writeUtf8
7373 -- , writeUtf8ByLines
7474 -- , writeByFrames
75− , writeInChunksOf
75+ , writeRequestsOf
7676
7777 -- -- * Array Write
7878 , writeArray
79− , writeArrays
79+ , writeChunks
8080
8181 -- ** Append To File
8282 , append
83− , appendByChunks
83+ , appendRequestsOf
8484 -- , appendShared
8585 , appendArray
86− , appendArrays
86+ , appendChunks
8787
8888 -- -- * Random Access (Seek)
8989 -- -- | 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)
182182-- Stream of Arrays IO
183183-------------------------------------------------------------------------------
184184
185−-- | @toStreamArraysOf size file@ reads a stream of arrays from file @file@.
185+-- | @toChunksRequestsOf size file@ reads a stream of arrays from file @file@.
186186-- The maximum size of a single array is specified by @size@. The actual size
187187-- read may be less than or equal to @size@.
188−{-# INLINABLE toStreamArraysOf #-}
189−toStreamArraysOf :: (IsStream t, MonadCatch m, MonadIO m)
188+{-# INLINABLE toChunksRequestsOf #-}
189+toChunksRequestsOf :: (IsStream t, MonadCatch m, MonadIO m)
190190 => Int -> FilePath -> t m (Array Word8)
191−toStreamArraysOf size file = withFile file ReadMode (FH.toStreamArraysOf size)
191+toChunksRequestsOf size file =
192+ withFile file ReadMode (FH.toChunksRequestsOf size)
192193
193194-- XXX read 'Array a' instead of Word8
194195--
195−-- | @toStreamArrays file@ reads a stream of arrays from file @file@.
196+-- | @toChunks file@ reads a stream of arrays from file @file@.
196197-- The maximum size of a single array is limited to @defaultChunkSize@. The
197198-- actual size read may be less than @defaultChunkSize@.
198199--
199−-- > toStreamArrays = toStreamArraysOf defaultChunkSize
200+-- > toChunks = toChunksRequestsOf defaultChunkSize
200201--
201202-- @since 0.7.0
202−{-# INLINE toStreamArrays #-}
203−toStreamArrays :: (IsStream t, MonadCatch m, MonadIO m)
203+{-# INLINE toChunks #-}
204+toChunks :: (IsStream t, MonadCatch m, MonadIO m)
204205 => FilePath -> t m (Array Word8)
205−toStreamArrays = toStreamArraysOf defaultChunkSize
206+toChunks = toChunksRequestsOf defaultChunkSize
206207
207208-------------------------------------------------------------------------------
208209-- Read File to Stream
@@ -219,7 +220,7 @@ toStreamArrays = toStreamArraysOf defaultChunkSize
219220--
220221{-# INLINE readInChunksOf #-}
221222readInChunksOf :: (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
223224-}
224225
225226-- TODO
@@ -233,7 +234,7 @@ readInChunksOf chunkSize h = A.flattenArrays $ toStreamArraysOf chunkSize h
233234-- @since 0.7.0
234235{-# INLINE read #-}
235236read :: (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
237238
238239{-
239240-- | Generate a stream of elements of the given type from a file 'Handle'. The
@@ -259,19 +260,19 @@ readTailForever = undefined
259260-- Writing
260261-------------------------------------------------------------------------------
261262
262−{-# INLINE writeArraysMode #-}
263−writeArraysMode :: (MonadAsync m, MonadCatch m, Storable a)
263+{-# INLINE writeChunksMode #-}
264+writeChunksMode :: (MonadAsync m, MonadCatch m, Storable a)
264265 => IOMode -> FilePath -> SerialT m (Array a) -> m ()
265−writeArraysMode mode file xs = S.drain $
266+writeChunksMode mode file xs = S.drain $
266267 withFile file mode (\h -> S.mapM (liftIO . FH.writeArray h) xs)
267268
268269-- | Write a stream of arrays to a file. Overwrites the file if it exists.
269270--
270271-- @since 0.7.0
271−{-# INLINE writeArrays #-}
272−writeArrays :: (MonadAsync m, MonadCatch m, Storable a)
272+{-# INLINE writeChunks #-}
273+writeChunks :: (MonadAsync m, MonadCatch m, Storable a)
273274 => FilePath -> SerialT m (Array a) -> m ()
274−writeArrays = writeArraysMode WriteMode
275+writeChunks = writeChunksMode WriteMode
275276
276277-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
277278--
@@ -286,12 +287,12 @@ writeArrays = writeArraysMode WriteMode
286287-- input elements.
287288--
288289-- @since 0.7.0
289−{-# INLINE writeInChunksOf #-}
290−writeInChunksOf :: (MonadAsync m, MonadCatch m)
290+{-# INLINE writeRequestsOf #-}
291+writeRequestsOf :: (MonadAsync m, MonadCatch m)
291292 => 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
293294
294−-- > write = 'writeInChunksOf' defaultChunkSize
295+-- > write = 'writeRequestsOf' defaultChunkSize
295296--
296297-- | Write a byte stream to a file. Combines the bytes in chunks of size
297298-- 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
301302-- @since 0.7.0
302303{-# INLINE write #-}
303304write :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
304−write = writeInChunksOf defaultChunkSize
305+write = writeRequestsOf defaultChunkSize
305306
306307{-
307308{-# INLINE write #-}
@@ -312,20 +313,20 @@ write = toHandleWith A.defaultChunkSize
312313-- | Append a stream of arrays to a file.
313314--
314315-- @since 0.7.0
315−{-# INLINE appendArrays #-}
316−appendArrays :: (MonadAsync m, MonadCatch m, Storable a)
316+{-# INLINE appendChunks #-}
317+appendChunks :: (MonadAsync m, MonadCatch m, Storable a)
317318 => FilePath -> SerialT m (Array a) -> m ()
318−appendArrays = writeArraysMode AppendMode
319+appendChunks = writeChunksMode AppendMode
319320
320321-- | Like 'append' but provides control over the write buffer. Output will
321322-- be written to the IO device as soon as we collect the specified number of
322323-- input elements.
323324--
324325-- @since 0.7.0
325−{-# INLINE appendByChunks #-}
326−appendByChunks :: (MonadAsync m, MonadCatch m)
326+{-# INLINE appendRequestsOf #-}
327+appendRequestsOf :: (MonadAsync m, MonadCatch m)
327328 => 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
329330
330331-- | Append a byte stream to a file. Combines the bytes in chunks of size up to
331332-- '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
335336-- @since 0.7.0
336337{-# INLINE append #-}
337338append :: (MonadAsync m, MonadCatch m) => FilePath -> SerialT m Word8 -> m ()
338−append = appendByChunks defaultChunkSize
339+append = appendRequestsOf defaultChunkSize
339340
340341{-
341342-- | 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
2222 -- , readUtf8
2323 -- , readLines
2424 -- , readFrames
25− , readInChunksOf
25+ , readRequestsOf
2626
2727 , toStream
28− , toStreamInChunksOf
28+ , toStreamRequestsOf
2929
3030 -- -- * Array Read
3131 -- , readArrayUpto
3232 -- , readArrayOf
33− , readArraysOf
34− , readArrays
33+ , readChunks
34+ , readChunksRequestsOf
3535
36− , toStreamArraysOf
37− , toStreamArrays
36+ , toChunksRequestsOf
37+ , toChunks
3838
3939 -- ** Write to Handle
4040 -- Byte stream write (Folds)
@@ -42,7 +42,7 @@ module Streamly.Internal.FileSystem.Handle
4242 -- , writeUtf8
4343 -- , writeUtf8ByLines
4444 -- , writeByFrames
45− , writeInChunksOf
45+ , writeRequestsOf
4646
4747 -- Byte stream write (Streams)
4848 , fromStream
@@ -50,8 +50,8 @@ module Streamly.Internal.FileSystem.Handle
5050
5151 -- -- * Array Write
5252 , writeArray
53− , writeArrays
54− , writeArraysInChunksOf
53+ , writeChunks
54+ , writeChunksRequestsOf
5555
5656 -- -- * Array stream Write
5757 , fromStreamArrays
@@ -63,18 +63,37 @@ module Streamly.Internal.FileSystem.Handle
6363 -- include disks, files, memory devices and exclude terminals, pipes,
6464 -- sockets and fifos.
6565 --
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+ --
6672 -- , readIndex
67− -- , readSlice
68− -- , readSliceRev
69− -- , readAt -- read from a given position to th end of file
70− -- , readSliceArrayUpto
71− -- , readSliceArrayOf
73+ -- , readFrom -- read from a given position to the end of file
74+ -- , readFromRev -- read from a given position the beginning of file
75+ -- , readTo -- read from beginning up to the given position
76+ -- , readToRev -- read from end to the given position in file
77+ -- , readFromTo
78+ -- , readFromThenTo
79+
80+ -- , readChunksFrom
81+ -- , readChunksFromTo
82+ -- , readChunksFromToRequestsOf
83+ -- , readChunksFromThenToRequestsOf
7284
7385 -- , writeIndex
74− -- , writeSlice
75− -- , writeSliceRev
76− -- , writeAt -- start writing at the given position
77− -- , writeSliceArray
86+ -- , writeFrom -- start writing at the given position
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
7897 )
7998where
8099
@@ -145,13 +164,13 @@ readArrayUpto size h = do
145164-- Stream of Arrays IO
146165-------------------------------------------------------------------------------
147166
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@.
149168-- The maximum size of a single array is specified by @size@. The actual size
150169-- read may be less than or equal to @size@.
151−{-# INLINABLE _toStreamArraysOf #-}
152−_toStreamArraysOf :: (IsStream t, MonadIO m)
170+{-# INLINABLE _toChunksRequestsOf #-}
171+_toChunksRequestsOf :: (IsStream t, MonadIO m)
153172 => Int -> Handle -> t m (Array Word8)
154−_toStreamArraysOf size h = go
173+_toChunksRequestsOf size h = go
155174 where
156175 -- XXX use cons/nil instead
157176 go = mkStream $ \_ yld _ stp -> do
@@ -160,14 +179,14 @@ _toStreamArraysOf size h = go
160179 then stp
161180 else yld arr go
162181
163−-- | @toStreamArraysOf size handle@ reads a stream of arrays from the file
182+-- | @toChunksRequestsOf size handle@ reads a stream of arrays from the file
164183-- handle @handle@. The maximum size of a single array is limited to @size@.
165184-- The actual size read may be less than or equal to @size@.
166185--
167186-- @since 0.7.0
168−{-# INLINE_NORMAL toStreamArraysOf #-}
169−toStreamArraysOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m (Array Word8)
170−toStreamArraysOf size h = D.fromStreamD (D.Stream step ())
187+{-# INLINE_NORMAL toChunksRequestsOf #-}
188+toChunksRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m (Array Word8)
189+toChunksRequestsOf size h = D.fromStreamD (D.Stream step ())
171190 where
172191 {-# INLINE_LATE step #-}
173192 step _ _ = do
@@ -179,12 +198,12 @@ toStreamArraysOf size h = D.fromStreamD (D.Stream step ())
179198
180199-- | Unfold the tuple @(size, handle)@ into a stream of 'Word8' arrays. The
181200-- 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@.
183202--
184203-- @since 0.7.0
185−{-# INLINE_NORMAL readArraysOf #-}
186−readArraysOf :: MonadIO m => Unfold m (Int, Handle) (Array Word8)
187−readArraysOf = Unfold step return
204+{-# INLINE_NORMAL readChunksRequestsOf #-}
205+readChunksRequestsOf :: MonadIO m => Unfold m (Int, Handle) (Array Word8)
206+readChunksRequestsOf = Unfold step return
188207 where
189208 {-# INLINE_LATE step #-}
190209 step (size, h) = do
@@ -196,25 +215,28 @@ readArraysOf = Unfold step return
196215
197216-- XXX read 'Array a' instead of Word8
198217--
199−-- | @toStreamArrays handle@ reads a stream of arrays from the specified file
218+-- | @toChunks handle@ reads a stream of arrays from the specified file
200219-- handle. The maximum size of a single array is limited to
201220-- @defaultChunkSize@. The actual size read may be less than or equal to
202221-- @defaultChunkSize@.
203222--
204−-- > toStreamArrays = toStreamArraysOf defaultChunkSize
223+-- > toChunks = toChunksRequestsOf defaultChunkSize
205224--
206225-- @since 0.7.0
207−{-# INLINE toStreamArrays #-}
208−toStreamArrays :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
209−toStreamArrays = toStreamArraysOf defaultChunkSize
226+{-# INLINE toChunks #-}
227+toChunks :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
228+toChunks = toChunksRequestsOf defaultChunkSize
210229
211−-- | Unfolds a handle into a stream of 'Word8' arrays. The maximum size of a
212−-- single array is limited to @defaultChunkSize@.
230+-- | Unfolds a handle into a stream of 'Word8' arrays. Requests to the IO
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'.
213235--
214236-- @since 0.7.0
215−{-# INLINE readArrays #-}
216−readArrays :: MonadIO m => Unfold m Handle (Array Word8)
217−readArrays = UF.supplyFirst readArraysOf defaultChunkSize
237+{-# INLINE readChunks #-}
238+readChunks :: MonadIO m => Unfold m Handle (Array Word8)
239+readChunks = UF.supplyFirst readChunksRequestsOf defaultChunkSize
218240
219241-------------------------------------------------------------------------------
220242-- Read File to Stream
@@ -224,40 +246,41 @@ readArrays = UF.supplyFirst readArraysOf defaultChunkSize
224246-- read requests at the same time. For serial case we can use async IO. We can
225247-- also control the read throughput in mbps or IOPS.
226248
227−-- | @readInChunksOf@ unfolds @(chunksize, handle)@ into a byte stream, reads
228−-- are performed in chunks of up to @chunkSize@.
249+-- | Unfolds the tuple @(chunksize, handle)@ into a byte stream, read requests
250+-- to the IO device are performed using buffers of @chunkSize@.
229251--
230252-- @since 0.7.0
231−{-# INLINE readInChunksOf #-}
232−readInChunksOf :: MonadIO m => Unfold m (Int, Handle) Word8
233−readInChunksOf = UF.concat readArraysOf A.read
253+{-# INLINE readRequestsOf #-}
254+readRequestsOf :: MonadIO m => Unfold m (Int, Handle) Word8
255+readRequestsOf = UF.concat readChunksRequestsOf A.read
234256
235−-- | @toStreamInChunksOf chunkSize handle@ reads a byte stream from a file
257+-- | @toStreamRequestsOf chunkSize handle@ reads a byte stream from a file
236258-- handle, reads are performed in chunks of up to @chunkSize@.
237259--
238260-- /Internal/
239−{-# INLINE toStreamInChunksOf #-}
240−toStreamInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
241−toStreamInChunksOf chunkSize h = AS.concat $ toStreamArraysOf chunkSize h
261+{-# INLINE toStreamRequestsOf #-}
262+toStreamRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
263+toStreamRequestsOf chunkSize h = AS.concat $ toChunksRequestsOf chunkSize h
242264
243265-- TODO
244266-- Generate a stream of elements of the given type from a file 'Handle'.
245267-- read :: (IsStream t, MonadIO m, Storable a) => Handle -> t m a
246268--
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'.
249272--
250273-- @since 0.7.0
251274{-# INLINE read #-}
252275read :: MonadIO m => Unfold m Handle Word8
253−read = UF.supplyFirst readInChunksOf defaultChunkSize
276+read = UF.supplyFirst readRequestsOf defaultChunkSize
254277
255278-- | Generate a byte stream from a file 'Handle'.
256279--
257280-- /Internal/
258281{-# INLINE toStream #-}
259282toStream :: (IsStream t, MonadIO m) => Handle -> t m Word8
260−toStream = AS.concat . toStreamArrays
283+toStream = AS.concat . toChunks
261284
262285-------------------------------------------------------------------------------
263286-- Writing
@@ -316,10 +339,10 @@ fromStreamInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
316339fromStreamInChunksOf n h m = fromStreamArrays h $ S.arraysOf n m
317340-- fromStreamInChunksOf n h m = fromStreamArrays h $ AS.arraysOf n m
318341
319−-- > write = 'writeInChunksOf' A.defaultChunkSize
342+-- > write = 'writeRequestsOf' A.defaultChunkSize
320343--
321344-- | 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.
323346--
324347-- NOTE: This may perform better than the 'write' fold, you can try this if you
325348-- need some extra perf boost.
@@ -329,24 +352,25 @@ fromStreamInChunksOf n h m = fromStreamArrays h $ S.arraysOf n m
329352fromStream :: MonadIO m => Handle -> SerialT m Word8 -> m ()
330353fromStream = fromStreamInChunksOf defaultChunkSize
331354
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.
333357--
334358-- @since 0.7.0
335−{-# INLINE writeArrays #-}
336−writeArrays :: (MonadIO m, Storable a) => Handle -> Fold m (Array a) ()
337−writeArrays h = FL.drainBy (liftIO . writeArray h)
359+{-# INLINE writeChunks #-}
360+writeChunks :: (MonadIO m, Storable a) => Handle -> Fold m (Array a) ()
361+writeChunks h = FL.drainBy (liftIO . writeArray h)
338362
339−-- | @writeArraysInChunksOf chunkSize handle@ writes a stream of arrays
363+-- | @writeChunksRequestsOf chunkSize handle@ writes a stream of arrays
340364-- to @handle@ after coalescing the adjacent arrays in chunks of @chunkSize@.
341365-- We never split an array, if a single array is bigger than the specified size
342366-- it emitted as it is. Multiple arrays are coalesed as long as the total size
343367-- remains below the specified size.
344368--
345369-- @since 0.7.0
346−{-# INLINE writeArraysInChunksOf #-}
347−writeArraysInChunksOf :: (MonadIO m, Storable a)
370+{-# INLINE writeChunksRequestsOf #-}
371+writeChunksRequestsOf :: (MonadIO m, Storable a)
348372 => Int -> Handle -> Fold m (Array a) ()
349−writeArraysInChunksOf n h = lpackArraysChunksOf n (writeArrays h)
373+writeChunksRequestsOf n h = lpackArraysChunksOf n (writeChunks h)
350374
351375-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
352376--
@@ -356,24 +380,25 @@ writeArraysInChunksOf n h = lpackArraysChunksOf n (writeArrays h)
356380-- do not want buffering to occur at GHC level as well. Same thing applies to
357381-- writes as well.
358382
359−-- | @writeInChunksOf chunkSize handle@ writes the input stream to @handle@ in
360−-- chunks of @chunkSize@. A write is performed to the IO device as soon as we
361−-- collect the required input size.
383+-- | @writeRequestsOf reqSize handle@ writes the input stream to @handle@.
384+-- Bytes in the input stream are collected into a buffer until we have a chunk
385+-- of @reqSize@ and then written to the IO device.
362386--
363387-- @since 0.7.0
364−{-# INLINE writeInChunksOf #-}
365−writeInChunksOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
366−writeInChunksOf n h = FL.lchunksOf n (writeNUnsafe n) (writeArrays h)
388+{-# INLINE writeRequestsOf #-}
389+writeRequestsOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
390+writeRequestsOf n h = FL.lchunksOf n (writeNUnsafe n) (writeChunks h)
367391
368−-- > write = 'writeInChunksOf' A.defaultChunkSize
392+-- > write = 'writeRequestsOf' A.defaultChunkSize
369393--
370394-- | 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.
372397--
373398-- @since 0.7.0
374399{-# INLINE write #-}
375400write :: MonadIO m => Handle -> Fold m Word8 ()
376−write = writeInChunksOf defaultChunkSize
401+write = writeRequestsOf defaultChunkSize
377402
378403{-
379404{-# INLINE write #-}
src/Streamly/Internal/Network/Inet/TCP.hs+24−24
@@ -53,20 +53,20 @@ module Streamly.Internal.Network.Inet.TCP
5353 -- , readArrayUpto
5454 -- , readArrayOf
5555
56− -- , readArraysUpto
57− -- , readArraysOf
58− -- , readArrays
56+ -- , readChunksUpto
57+ -- , readChunksOf
58+ -- , readChunks
5959
6060 -- *** Sink
6161 , write
6262 -- , writeUtf8
6363 -- , writeUtf8ByLines
6464 -- , writeByFrames
65− -- , writeInChunksOf
65+ -- , writeRequestsOf
6666
6767 -- -- * Array Write
6868 -- , writeArray
69− , writeArrays
69+ , writeChunks
7070 {-
7171 -- ** Sink Servers
7272
@@ -283,7 +283,7 @@ withConnection addr port =
283283{-# INLINE read #-}
284284read :: (MonadCatch m, MonadIO m)
285285 => 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
287287
288288-- | Read a stream from the supplied IPv4 host address and port number.
289289--
@@ -291,7 +291,7 @@ read = UF.concat (withServerAddr ISK.readArrays) A.read
291291{-# INLINE toStream #-}
292292toStream :: (IsStream t, MonadCatch m, MonadIO m)
293293 => (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
295295
296296-------------------------------------------------------------------------------
297297-- Writing
@@ -302,32 +302,32 @@ toStream addr port = AS.concat $ withConnection addr port ISK.toStreamArrays
302302-- number.
303303--
304304-- @since 0.7.0
305−{-# INLINE writeArrays #-}
306−writeArrays
305+{-# INLINE writeChunks #-}
306+writeChunks
307307 :: (MonadCatch m, MonadAsync m)
308308 => (Word8, Word8, Word8, Word8)
309309 -> PortNumber
310310 -> SerialT m (Array Word8)
311311 -> m ()
312−writeArrays addr port xs =
313− S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.writeArrays sk xs)
312+writeChunks addr port xs =
313+ S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.writeChunks sk xs)
314314-}
315315
316316-- | Write a stream of arrays to the supplied IPv4 host address and port
317317-- number.
318318--
319319-- @since 0.7.0
320−{-# INLINE writeArrays #-}
321−writeArrays
320+{-# INLINE writeChunks #-}
321+writeChunks
322322 :: (MonadAsync m)
323323 => (Word8, Word8, Word8, Word8)
324324 -> PortNumber
325325 -> Fold m (Array Word8) ()
326−writeArrays addr port = Fold step initial extract
326+writeChunks addr port = Fold step initial extract
327327 where
328328 initial = do
329329 skt <- liftIO (connect addr port)
330− FL.initialize (SK.writeArrays skt)
330+ FL.initialize (SK.writeChunks skt)
331331 step = FL.runStep
332332 extract (Fold _ initial1 extract1) = initial1 >>= extract1
333333
@@ -337,15 +337,15 @@ writeArrays addr port = Fold step initial extract
337337-- input elements.
338338--
339339-- @since 0.7.0
340−{-# INLINE writeInChunksOf #-}
341−writeInChunksOf
340+{-# INLINE writeRequestsOf #-}
341+writeRequestsOf
342342 :: (MonadCatch m, MonadAsync m)
343343 => Int
344344 -> (Word8, Word8, Word8, Word8)
345345 -> PortNumber
346346 -> SerialT m Word8
347347 -> 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
349349-}
350350
351351-- | 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
353353-- input elements.
354354--
355355-- @since 0.7.0
356−{-# INLINE writeInChunksOf #-}
357−writeInChunksOf
356+{-# INLINE writeRequestsOf #-}
357+writeRequestsOf
358358 :: (MonadAsync m)
359359 => Int
360360 -> (Word8, Word8, Word8, Word8)
361361 -> PortNumber
362362 -> Fold m Word8 ()
363−writeInChunksOf n addr port =
364− FL.lchunksOf n (writeNUnsafe n) (writeArrays addr port)
363+writeRequestsOf n addr port =
364+ FL.lchunksOf n (writeNUnsafe n) (writeChunks addr port)
365365
366366{-
367367-- | Write a stream to the supplied IPv4 host address and port number.
@@ -370,7 +370,7 @@ writeInChunksOf n addr port =
370370{-# INLINE write #-}
371371write :: (MonadCatch m, MonadAsync m)
372372 => (Word8, Word8, Word8, Word8) -> PortNumber -> SerialT m Word8 -> m ()
373−write = writeInChunksOf defaultChunkSize
373+write = writeRequestsOf defaultChunkSize
374374-}
375375
376376-- | Write a stream to the supplied IPv4 host address and port number.
@@ -379,4 +379,4 @@ write = writeInChunksOf defaultChunkSize
379379{-# INLINE write #-}
380380write :: MonadAsync m
381381 => (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
2929
3030 -- * Read from connection
3131 , read
32+ , readRequestsOf
3233 -- , readUtf8
3334 -- , readLines
3435 -- , readFrames
@@ -39,23 +40,23 @@ module Streamly.Internal.Network.Socket
3940 -- , readArrayUpto
4041 -- , readArrayOf
4142
42− -- , readArraysUpto
43− , readArraysOf
44− , readArrays
43+ -- , readChunksUpto
44+ , readChunksRequestsOf
45+ , readChunks
4546
46− , toStreamArraysOf
47− , toStreamArrays
47+ , toChunksRequestsOf
48+ , toChunks
4849
4950 -- * Write to connection
5051 , write
5152 -- , writeUtf8
5253 -- , writeUtf8ByLines
5354 -- , writeByFrames
54− , writeInChunksOf
55+ , writeRequestsOf
5556
5657 -- -- * Array Write
5758 , writeArray
58− , writeArrays
59+ , writeChunks
5960
6061 -- reading/writing datagrams
6162 )
@@ -281,11 +282,11 @@ writeArray = writeArrayWith sendAll
281282-- Stream of Arrays IO
282283-------------------------------------------------------------------------------
283284
284−{-# INLINABLE readArraysUptoWith #-}
285−readArraysUptoWith :: (IsStream t, MonadIO m)
285+{-# INLINABLE readChunksUptoWith #-}
286+readChunksUptoWith :: (IsStream t, MonadIO m)
286287 => (Int -> h -> IO (Array Word8))
287288 -> Int -> h -> t m (Array Word8)
288−readArraysUptoWith f size h = go
289+readChunksUptoWith f size h = go
289290 where
290291 -- XXX use cons/nil instead
291292 go = mkStream $ \_ yld _ stp -> do
@@ -294,33 +295,34 @@ readArraysUptoWith f size h = go
294295 then stp
295296 else yld arr go
296297
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@.
298299-- The maximum size of a single array is limited to @size@.
299300-- 'fromHandleArraysUpto' ignores the prevailing 'TextEncoding' and 'NewlineMode'
300301-- on the 'Handle'.
301−{-# INLINABLE toStreamArraysOf #-}
302−toStreamArraysOf :: (IsStream t, MonadIO m)
302+{-# INLINABLE toChunksRequestsOf #-}
303+toChunksRequestsOf :: (IsStream t, MonadIO m)
303304 => Int -> Socket -> t m (Array Word8)
304−toStreamArraysOf = readArraysUptoWith readArrayOf
305+toChunksRequestsOf = readChunksUptoWith readArrayOf
305306
306307-- XXX read 'Array a' instead of Word8
307308--
308−-- | @toStreamArrays h@ reads a stream of arrays from socket handle @h@.
309+-- | @toChunks h@ reads a stream of arrays from socket handle @h@.
309310-- The maximum size of a single array is limited to @defaultChunkSize@.
310311--
311312-- @since 0.7.0
312−{-# INLINE toStreamArrays #-}
313−toStreamArrays :: (IsStream t, MonadIO m) => Socket -> t m (Array Word8)
314−toStreamArrays = toStreamArraysOf A.defaultChunkSize
313+{-# INLINE toChunks #-}
314+toChunks :: (IsStream t, MonadIO m) => Socket -> t m (Array Word8)
315+toChunks = toChunksRequestsOf A.defaultChunkSize
315316
316317-- | Unfold the tuple @(size, socket)@ into a stream of 'Word8' arrays. The
317318-- 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@.
319321--
320322-- @since 0.7.0
321−{-# INLINE_NORMAL readArraysOf #-}
322−readArraysOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8)
323−readArraysOf = Unfold step return
323+{-# INLINE_NORMAL readChunksRequestsOf #-}
324+readChunksRequestsOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8)
325+readChunksRequestsOf = Unfold step return
324326 where
325327 {-# INLINE_LATE step #-}
326328 step (size, h) = do
@@ -330,13 +332,16 @@ readArraysOf = Unfold step return
330332 0 -> D.Stop
331333 _ -> D.Yield arr (size, h)
332334
333−-- | Unfolds a socket into a stream of 'Word8' arrays. The maximum size of a
334−-- single array is limited to @defaultChunkSize@.
335+-- | Unfolds a socket into a stream of 'Word8' arrays. Requests to the socket
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'.
335340--
336341-- @since 0.7.0
337−{-# INLINE readArrays #-}
338−readArrays :: MonadIO m => Unfold m Socket (Array Word8)
339−readArrays = UF.supplyFirst readArraysOf A.defaultChunkSize
342+{-# INLINE readChunks #-}
343+readChunks :: MonadIO m => Unfold m Socket (Array Word8)
344+readChunks = UF.supplyFirst readChunksRequestsOf A.defaultChunkSize
340345
341346-------------------------------------------------------------------------------
342347-- Read File to Stream
@@ -347,13 +352,13 @@ readArrays = UF.supplyFirst readArraysOf A.defaultChunkSize
347352-- also control the read throughput in mbps or IOPS.
348353
349354{-
350−-- | @readInChunksOf chunkSize handle@ reads a byte stream from a file
355+-- | @readRequestsOf chunkSize handle@ reads a byte stream from a file
351356-- handle, reads are performed in chunks of up to @chunkSize@. The stream ends
352357-- as soon as EOF is encountered.
353358--
354−{-# INLINE readInChunksOf #-}
355−readInChunksOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
356−readInChunksOf chunkSize h = A.flattenArrays $ readArraysUpto chunkSize h
359+{-# INLINE readRequestsOf #-}
360+readRequestsOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
361+readRequestsOf chunkSize h = A.flattenArrays $ readChunksUpto chunkSize h
357362-}
358363
359364-- TODO
@@ -366,22 +371,24 @@ readInChunksOf chunkSize h = A.flattenArrays $ readArraysUpto chunkSize h
366371-- @since 0.7.0
367372{-# INLINE toStream #-}
368373toStream :: (IsStream t, MonadIO m) => Socket -> t m Word8
369−toStream = AS.concat . toStreamArrays
374+toStream = AS.concat . toChunks
370375
371−-- | @readInChunksOf@ unfolds @(bufsize, socket)@ into a byte stream, reads
372−-- are performed in buffers of up to @bufsize@.
376+-- | Unfolds the tuple @(chunksize, socket)@ into a byte stream, read requests
377+-- to the socket are performed using buffers of @chunkSize@.
373378--
374379-- @since 0.7.0
375−{-# INLINE readInChunksOf #-}
376−readInChunksOf :: MonadIO m => Unfold m (Int, Socket) Word8
377−readInChunksOf = UF.concat readArraysOf A.read
380+{-# INLINE readRequestsOf #-}
381+readRequestsOf :: MonadIO m => Unfold m (Int, Socket) Word8
382+readRequestsOf = UF.concat readChunksRequestsOf A.read
378383
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'.
380387--
381388-- @since 0.7.0
382389{-# INLINE read #-}
383390read :: MonadIO m => Unfold m Socket Word8
384−read = UF.supplyFirst readInChunksOf A.defaultChunkSize
391+read = UF.supplyFirst readRequestsOf A.defaultChunkSize
385392
386393-------------------------------------------------------------------------------
387394-- Writing
@@ -390,17 +397,18 @@ read = UF.supplyFirst readInChunksOf A.defaultChunkSize
390397-- | Write a stream of arrays to a handle.
391398--
392399-- @since 0.7.0
393−{-# INLINE writeArraysS #-}
394−writeArraysS :: (MonadIO m, Storable a)
400+{-# INLINE writeChunksS #-}
401+writeChunksS :: (MonadIO m, Storable a)
395402 => 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
397404
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.
399407--
400408-- @since 0.7.0
401−{-# INLINE writeArrays #-}
402−writeArrays :: (MonadIO m, Storable a) => Socket -> Fold m (Array a) ()
403−writeArrays h = FL.drainBy (liftIO . writeArray h)
409+{-# INLINE writeChunks #-}
410+writeChunks :: (MonadIO m, Storable a) => Socket -> Fold m (Array a) ()
411+writeChunks h = FL.drainBy (liftIO . writeArray h)
404412
405413-- GHC buffer size dEFAULT_FD_BUFFER_SIZE=8192 bytes.
406414--
@@ -415,19 +423,19 @@ writeArrays h = FL.drainBy (liftIO . writeArray h)
415423-- input elements.
416424--
417425-- @since 0.7.0
418−{-# INLINE writeInChunksOfS #-}
419−writeInChunksOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
420−writeInChunksOfS n h m = writeArraysS h $ AS.arraysOf n m
426+{-# INLINE writeRequestsOfS #-}
427+writeRequestsOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
428+writeRequestsOfS n h m = writeChunksS h $ AS.arraysOf n m
421429
422430-- | Write a byte stream to a socket. Accumulates the input in chunks of
423431-- specified number of bytes before writing.
424432--
425433-- @since 0.7.0
426−{-# INLINE writeInChunksOf #-}
427−writeInChunksOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
428−writeInChunksOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeArrays h)
434+{-# INLINE writeRequestsOf #-}
435+writeRequestsOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
436+writeRequestsOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeChunks h)
429437
430−-- > write = 'writeInChunksOf' A.defaultChunkSize
438+-- > write = 'writeRequestsOf' A.defaultChunkSize
431439--
432440-- | Write a byte stream to a file handle. Combines the bytes in chunks of size
433441-- 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)
436444-- @since 0.7.0
437445{-# INLINE _writeS #-}
438446_writeS :: MonadIO m => Socket -> SerialT m Word8 -> m ()
439−_writeS = writeInChunksOfS A.defaultChunkSize
447+_writeS = writeRequestsOfS A.defaultChunkSize
440448
441449-- | Write a byte stream to a socket. Accumulates the input in chunks of
442450-- up to 'A.defaultChunkSize' bytes before writing.
443451--
444452-- @
445−-- write = 'writeInChunksOf' 'A.defaultChunkSize'
453+-- write = 'writeRequestsOf' 'A.defaultChunkSize'
446454-- @
447455--
448456-- @since 0.7.0
449457{-# INLINE write #-}
450458write :: MonadIO m => Socket -> Fold m Word8 ()
451−write = writeInChunksOf A.defaultChunkSize
459+write = writeRequestsOf A.defaultChunkSize
452460
453461{-
454462{-# INLINE write #-}
src/Streamly/Memory/Array.hs+19−37
@@ -16,48 +16,30 @@
1616-- Stability : experimental
1717-- Portability : GHC
1818--
19−-- This module provides immutable arrays suitable for storage and random
20−-- access. Once created an array cannot be mutated without copying. Arrays in
21−-- this module are chunks of memory that hold a sequence of 'Storable' values
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.
19+-- This module provides immutable arrays in pinned memory (non GC memory)
20+-- suitable for long lived data storage, random access and for interfacing with
21+-- the operating system.
2922--
30−-- By design, there are no array transformation operations provided in this
31−-- module, only conversion to and from stream is provided. Arrays can be
32−-- operated upon /efficiently/ by converting them into a stream, applying the
33−-- desired stream transformations from "Streamly.Prelude" and then converting
34−-- it back to an array.
23+-- Arrays in this module are chunks of pinned memory that hold a sequence of
24+-- 'Storable' values of a given type, they cannot store non-serializable data
25+-- like functions. Once created an array cannot be modified. Pinned memory
26+-- allows efficient buffering of long lived data without adding any impact to
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.
3531--
36−-- This module is designed to be imported qualified:
32+-- = Programmer Notes
3733--
38−-- > import qualified Streamly.Array as A
39−
40−-- To summarize:
34+-- To apply a transformation to an array use 'read' to unfold the array into a
35+-- stream, apply a transformation on the stream and then use 'write' to fold it
36+-- back to an array.
4137--
42−-- Arrays are finite and fixed in size
43−-- provide /O(1)/ access to elements
44−-- store only data and not functions
45−-- provide efficient IO interfacing
38+-- This module is designed to be imported qualified:
4639--
47−-- 'Foldable' instance is not provided because the implementation would be much
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.
40+-- > import qualified Streamly.Array as A
5241--
53−-- Each array is one pointer visible to the GC. Too many small arrays (e.g.
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.
42+-- For experimental APIs see "Streamly.Internal.Memory.Array".
6143
6244module Streamly.Memory.Array
6345 (
@@ -68,7 +50,7 @@ module Streamly.Memory.Array
6850 -- * Arrays
6951 -- ** Construction
7052 -- | 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
7254 -- used to conveniently construct arrays from literal values.
7355 -- 'OverloadedLists' extension or 'fromList' can be used to construct an
7456 -- array from a list literal. Similarly, 'OverloadedStrings' extension or
src/Streamly/Network/Socket.hs+13−27
@@ -15,15 +15,18 @@
1515-- for connected sockets do not need to explicitly specify the remote endpoint.
1616-- APIs for unconnected sockets need to explicitly specify the remote endpoint.
1717--
18+-- = Programmer Notes
19+--
1820-- Read IO requests to connected stream sockets are performed in chunks of
19−-- 32KiB, this is referred to as @defaultChunkSize@ in the documentation. One
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−-- they are written to the socket. APIs are provided to control the chunking
23−-- and framing behavior.
21+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'. Unless specified
22+-- otherwise in the API, writes are collected into chunks of
23+-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize' before they are
24+-- written to the socket. APIs are provided to control the chunking behavior.
2425--
2526-- > import qualified Streamly.Network.Socket as SK
2627--
28+-- For additional, experimental APIs take a look at
29+-- "Streamly.Internal.Network.Socket" module.
2730
2831-- By design, connected socket IO APIs are similar to
2932-- "Streamly.Memory.Array" read write APIs. They are almost identical to the
@@ -39,31 +42,14 @@ module Streamly.Network.Socket
3942
4043 -- * Read
4144 , read
42− -- , readUtf8
43− -- , readLines
44− -- , readFrames
45− -- , readByChunks
46−
47− -- -- * Array Read
48− -- , readArrayUpto
49− -- , readArrayOf
50−
51− -- , readArraysUpto
52− , readArraysOf
53− -- , readArrays
45+ , readRequestsOf
46+ , readChunks
47+ , readChunksRequestsOf
5448
5549 -- * Write
5650 , write
57− -- , writeUtf8
58− -- , writeUtf8ByLines
59− -- , writeByFrames
60− -- , writeInChunksOf
61−
62− -- -- * Array Write
63− -- , writeArray
64− , writeArrays
65−
66− -- reading/writing datagrams
51+ , writeRequestsOf
52+ , writeChunks
6753 )
6854where
6955