2-- Module : Stream.Exceptions
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
10{-# LANGUAGE FlexibleContexts #-}
11{-# LANGUAGE ScopedTypeVariables #-}
14{-# OPTIONS_GHC -Wno-deprecations #-}
17#ifdef __HADDOCK_VERSION__
22{-# LANGUAGE TemplateHaskell #-}
23{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
26module Stream.Exceptions (benchmarks) where
28import Control.Exception (Exception, throwIO)
29import Stream.Common (drain)
31import qualified Data.IORef as Ref
32import qualified Data.Map.Strict as Map
34import Control.Exception (SomeException)
35import System.IO (Handle, hClose, hPutChar)
36import qualified Streamly.FileSystem.Handle as FH
37import qualified Streamly.Internal.FileSystem.Handle as IFH
38import qualified Streamly.Internal.Data.Unfold as IUF
39import qualified Streamly.Internal.Data.Unfold.Exception as IUF
42import qualified Streamly.Internal.Data.Stream.IsStream as Stream
44import qualified Streamly.Internal.Data.Stream as Stream
45import qualified Streamly.Internal.Data.Stream.Exception.Lifted as Stream
48import Gauge hiding (env)
49import Prelude hiding (last, length)
50import Streamly.Benchmark.Common
51import Streamly.Benchmark.Common.Handle
56import qualified Streamly.Internal.Data.Stream as D
60type Stream = Stream.SerialT
61toStreamD = Stream.toStream
62fromStreamD = Stream.fromStream
64type Stream = Stream.Stream
71afterUnsafe :: IO b -> Stream IO a -> Stream IO a
72finallyUnsafe :: IO b -> Stream IO a -> Stream IO a
73bracketUnsafe :: IO b -> (b -> IO c) -> (b -> Stream IO a) -> Stream IO a
75afterUnsafe = Stream.after_
76finallyUnsafe = Stream.finally_
77bracketUnsafe = Stream.bracket_
79afterUnsafe = Stream.afterUnsafe
80finallyUnsafe = Stream.finallyUnsafe
81bracketUnsafe = Stream.bracketUnsafe
84-------------------------------------------------------------------------------
86-------------------------------------------------------------------------------
91 deriving (Show, Eq, Ord)
93instance Exception BenchException
95retryNoneSimple :: Int -> Int -> IO ()
96retryNoneSimple length from =
99 (Map.singleton BenchException1 length)
105 source = Stream.enumerateFromTo from (from + length)
107retryNone :: Int -> Int -> IO ()
108retryNone length from = do
109 ref <- Ref.newIORef (0 :: Int)
111 $ Stream.retry (Map.singleton BenchException1 length) (const Stream.nil)
117 Stream.replicateM (from + length)
118 $ Ref.modifyIORef' ref (+ 1) >> Ref.readIORef ref
120retryAll :: Int -> Int -> IO ()
121retryAll length from = do
122 ref <- Ref.newIORef 0
125 (Map.singleton BenchException1 (length + from)) (const Stream.nil)
133 Ref.modifyIORef' ref (+ 1)
134 val <- Ref.readIORef ref
137 else throwIO BenchException1
139retryUnknown :: Int -> Int -> IO ()
140retryUnknown length from = do
142 $ Stream.retry (Map.singleton BenchException1 length) (const source)
143 $ throwIO BenchException2 `Stream.before` Stream.nil
147 source = Stream.enumerateFromTo from (from + length)
150o_1_space_serial_exceptions :: Int -> [Benchmark]
151o_1_space_serial_exceptions length =
154 [ benchIOSrc1 "retryNoneSimple" (retryNoneSimple length)
155 , benchIOSrc1 "retryNone" (retryNone length)
156 , benchIOSrc1 "retryAll" (retryAll length)
157 , benchIOSrc1 "retryUnknown" (retryUnknown length)
161-- XXX Move these to FileSystem.Handle benchmarks
163-------------------------------------------------------------------------------
164-- copy stream exceptions
165-------------------------------------------------------------------------------
167-- | Send the file contents to /dev/null with exception handling
168readWriteOnExceptionStream :: Handle -> Handle -> IO ()
169readWriteOnExceptionStream inh devNull =
170 let readEx = Stream.onException (hClose inh) (Stream.unfold FH.reader inh)
171 in Stream.fold (FH.write devNull) readEx
174inspect $ hasNoTypeClasses 'readWriteOnExceptionStream
177-- | Send the file contents to /dev/null with exception handling
178readWriteHandleExceptionStream :: Handle -> Handle -> IO ()
179readWriteHandleExceptionStream inh devNull =
180 let handler (_e :: SomeException) =
181 return $ Stream.fromEffect (hClose inh >> return 10)
182 readEx = Stream.handle handler (Stream.unfold FH.reader inh)
183 in Stream.fold (FH.write devNull) readEx
186inspect $ hasNoTypeClasses 'readWriteHandleExceptionStream
189-- | Send the file contents to /dev/null with exception handling
190readWriteFinally_Stream :: Handle -> Handle -> IO ()
191readWriteFinally_Stream inh devNull =
193 finallyUnsafe (hClose inh) (Stream.unfold FH.reader inh)
194 in Stream.fold (FH.write devNull) readEx
197inspect $ hasNoTypeClasses 'readWriteFinally_Stream
200readWriteFinallyStream :: Handle -> Handle -> IO ()
201readWriteFinallyStream inh devNull =
202 let readEx = Stream.finally (hClose inh) (Stream.unfold FH.reader inh)
203 in Stream.fold (FH.write devNull) readEx
205-- | Send the file contents to /dev/null with exception handling
206fromToBytesBracket_Stream :: Handle -> Handle -> IO ()
207fromToBytesBracket_Stream inh devNull =
208 let readEx = bracketUnsafe (return ()) (\_ -> hClose inh)
209 (\_ -> fromStreamD $ IFH.read inh)
210 in IFH.putBytes devNull (toStreamD readEx)
213inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
216fromToBytesBracketStream :: Handle -> Handle -> IO ()
217fromToBytesBracketStream inh devNull =
218 let readEx = Stream.bracket (return ()) (\_ -> hClose inh)
219 (\_ -> fromStreamD $ IFH.read inh)
220 in IFH.putBytes devNull (toStreamD readEx)
222readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
223readWriteBeforeAfterStream inh devNull =
225 Stream.after (hClose inh)
226 $ Stream.before (hPutChar devNull 'A') (Stream.unfold FH.reader inh)
227 in Stream.fold (FH.write devNull) readEx
230inspect $ 'readWriteBeforeAfterStream `hasNoType` ''D.Step
233readWriteAfterStream :: Handle -> Handle -> IO ()
234readWriteAfterStream inh devNull =
235 let readEx = Stream.after (hClose inh) (Stream.unfold FH.reader inh)
236 in Stream.fold (FH.write devNull) readEx
239inspect $ 'readWriteAfterStream `hasNoType` ''D.Step
242readWriteAfter_Stream :: Handle -> Handle -> IO ()
243readWriteAfter_Stream inh devNull =
244 let readEx = afterUnsafe (hClose inh) (Stream.unfold FH.reader inh)
245 in Stream.fold (FH.write devNull) readEx
248inspect $ hasNoTypeClasses 'readWriteAfter_Stream
249inspect $ 'readWriteAfter_Stream `hasNoType` ''D.Step
252o_1_space_copy_stream_exceptions :: BenchEnv -> [Benchmark]
253o_1_space_copy_stream_exceptions env =
254 [ bgroup "exceptions"
255 [ mkBenchSmall "Stream.onException" env $ \inh _ ->
256 readWriteOnExceptionStream inh (nullH env)
257 , mkBenchSmall "Stream.handle" env $ \inh _ ->
258 readWriteHandleExceptionStream inh (nullH env)
259 , mkBenchSmall "Stream.finally_" env $ \inh _ ->
260 readWriteFinally_Stream inh (nullH env)
261 , mkBenchSmall "Stream.finally" env $ \inh _ ->
262 readWriteFinallyStream inh (nullH env)
263 , mkBenchSmall "Stream.after . Stream.before" env $ \inh _ ->
264 readWriteBeforeAfterStream inh (nullH env)
265 , mkBenchSmall "Stream.after" env $ \inh _ ->
266 readWriteAfterStream inh (nullH env)
267 , mkBenchSmall "Stream.after_" env $ \inh _ ->
268 readWriteAfter_Stream inh (nullH env)
270 , bgroup "exceptions/fromToBytes"
271 [ mkBenchSmall "Stream.bracket_" env $ \inh _ ->
272 fromToBytesBracket_Stream inh (nullH env)
273 , mkBenchSmall "Stream.bracket" env $ \inh _ ->
274 fromToBytesBracketStream inh (nullH env)
278 -------------------------------------------------------------------------------
279-- Exceptions readChunks
280-------------------------------------------------------------------------------
282-- | Send the file contents to /dev/null with exception handling
283readChunksOnException :: Handle -> Handle -> IO ()
284readChunksOnException inh devNull =
285 let readEx = IUF.onException (\_ -> hClose inh) FH.chunkReader
286 in IUF.fold (IFH.writeChunks devNull) readEx inh
289inspect $ hasNoTypeClasses 'readChunksOnException
292-- | Send the file contents to /dev/null with exception handling
293readChunksBracket_ :: Handle -> Handle -> IO ()
294readChunksBracket_ inh devNull =
295 let readEx = IUF.bracket_ return (\_ -> hClose inh) FH.chunkReader
296 in IUF.fold (IFH.writeChunks devNull) readEx inh
299inspect $ hasNoTypeClasses 'readChunksBracket_
302readChunksBracket :: Handle -> Handle -> IO ()
303readChunksBracket inh devNull =
304 let readEx = IUF.bracket return (\_ -> hClose inh) FH.chunkReader
305 in IUF.fold (IFH.writeChunks devNull) readEx inh
307o_1_space_copy_exceptions_readChunks :: BenchEnv -> [Benchmark]
308o_1_space_copy_exceptions_readChunks env =
309 [ bgroup "exceptions/readChunks"
310 [ mkBench "UF.onException" env $ \inH _ ->
311 readChunksOnException inH (nullH env)
312 , mkBench "UF.bracket_" env $ \inH _ ->
313 readChunksBracket_ inH (nullH env)
314 , mkBench "UF.bracket" env $ \inH _ ->
315 readChunksBracket inH (nullH env)
319-------------------------------------------------------------------------------
320-- Exceptions toChunks
321-------------------------------------------------------------------------------
323-- | Send the file contents to /dev/null with exception handling
324toChunksBracket_ :: Handle -> Handle -> IO ()
325toChunksBracket_ inh devNull =
326 let readEx = bracketUnsafe
329 (\_ -> fromStreamD $ IFH.readChunks inh)
330 in Stream.fold (IFH.writeChunks devNull) readEx
333inspect $ hasNoTypeClasses 'toChunksBracket_
336toChunksBracket :: Handle -> Handle -> IO ()
337toChunksBracket inh devNull =
338 let readEx = Stream.bracket
341 (\_ -> fromStreamD $ IFH.readChunks inh)
342 in Stream.fold (IFH.writeChunks devNull) readEx
344o_1_space_copy_exceptions_toChunks :: BenchEnv -> [Benchmark]
345o_1_space_copy_exceptions_toChunks env =
346 [ bgroup "exceptions/toChunks"
347 [ mkBench "Stream.bracket_" env $ \inH _ ->
348 toChunksBracket_ inH (nullH env)
349 , mkBench "Stream.bracket" env $ \inH _ ->
350 toChunksBracket inH (nullH env)
354benchmarks :: String -> BenchEnv -> Int -> [Benchmark]
355benchmarks moduleName _env size =
356 [ bgroup (o_1_space_prefix moduleName) $ concat
357 [ o_1_space_serial_exceptions size
358 , o_1_space_copy_exceptions_readChunks _env
359 , o_1_space_copy_exceptions_toChunks _env
360 , o_1_space_copy_stream_exceptions _env
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list