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.StreamD 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.StreamD 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) = Stream.fromEffect (hClose inh >> return 10)
181 readEx = Stream.handle handler (Stream.unfold FH.reader inh)
182 in Stream.fold (FH.write devNull) readEx
185inspect $ hasNoTypeClasses 'readWriteHandleExceptionStream
188-- | Send the file contents to /dev/null with exception handling
189readWriteFinally_Stream :: Handle -> Handle -> IO ()
190readWriteFinally_Stream inh devNull =
192 finallyUnsafe (hClose inh) (Stream.unfold FH.reader inh)
193 in Stream.fold (FH.write devNull) readEx
196inspect $ hasNoTypeClasses 'readWriteFinally_Stream
199readWriteFinallyStream :: Handle -> Handle -> IO ()
200readWriteFinallyStream inh devNull =
201 let readEx = Stream.finally (hClose inh) (Stream.unfold FH.reader inh)
202 in Stream.fold (FH.write devNull) readEx
204-- | Send the file contents to /dev/null with exception handling
205fromToBytesBracket_Stream :: Handle -> Handle -> IO ()
206fromToBytesBracket_Stream inh devNull =
207 let readEx = bracketUnsafe (return ()) (\_ -> hClose inh)
208 (\_ -> fromStreamD $ IFH.read inh)
209 in IFH.putBytes devNull (toStreamD readEx)
212inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
215fromToBytesBracketStream :: Handle -> Handle -> IO ()
216fromToBytesBracketStream inh devNull =
217 let readEx = Stream.bracket (return ()) (\_ -> hClose inh)
218 (\_ -> fromStreamD $ IFH.read inh)
219 in IFH.putBytes devNull (toStreamD readEx)
221readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
222readWriteBeforeAfterStream inh devNull =
224 Stream.after (hClose inh)
225 $ Stream.before (hPutChar devNull 'A') (Stream.unfold FH.reader inh)
226 in Stream.fold (FH.write devNull) readEx
229inspect $ 'readWriteBeforeAfterStream `hasNoType` ''D.Step
232readWriteAfterStream :: Handle -> Handle -> IO ()
233readWriteAfterStream inh devNull =
234 let readEx = Stream.after (hClose inh) (Stream.unfold FH.reader inh)
235 in Stream.fold (FH.write devNull) readEx
238inspect $ 'readWriteAfterStream `hasNoType` ''D.Step
241readWriteAfter_Stream :: Handle -> Handle -> IO ()
242readWriteAfter_Stream inh devNull =
243 let readEx = afterUnsafe (hClose inh) (Stream.unfold FH.reader inh)
244 in Stream.fold (FH.write devNull) readEx
247inspect $ hasNoTypeClasses 'readWriteAfter_Stream
248inspect $ 'readWriteAfter_Stream `hasNoType` ''D.Step
251o_1_space_copy_stream_exceptions :: BenchEnv -> [Benchmark]
252o_1_space_copy_stream_exceptions env =
253 [ bgroup "exceptions"
254 [ mkBenchSmall "Stream.onException" env $ \inh _ ->
255 readWriteOnExceptionStream inh (nullH env)
256 , mkBenchSmall "Stream.handle" env $ \inh _ ->
257 readWriteHandleExceptionStream inh (nullH env)
258 , mkBenchSmall "Stream.finally_" env $ \inh _ ->
259 readWriteFinally_Stream inh (nullH env)
260 , mkBenchSmall "Stream.finally" env $ \inh _ ->
261 readWriteFinallyStream inh (nullH env)
262 , mkBenchSmall "Stream.after . Stream.before" env $ \inh _ ->
263 readWriteBeforeAfterStream inh (nullH env)
264 , mkBenchSmall "Stream.after" env $ \inh _ ->
265 readWriteAfterStream inh (nullH env)
266 , mkBenchSmall "Stream.after_" env $ \inh _ ->
267 readWriteAfter_Stream inh (nullH env)
269 , bgroup "exceptions/fromToBytes"
270 [ mkBenchSmall "Stream.bracket_" env $ \inh _ ->
271 fromToBytesBracket_Stream inh (nullH env)
272 , mkBenchSmall "Stream.bracket" env $ \inh _ ->
273 fromToBytesBracketStream inh (nullH env)
277 -------------------------------------------------------------------------------
278-- Exceptions readChunks
279-------------------------------------------------------------------------------
281-- | Send the file contents to /dev/null with exception handling
282readChunksOnException :: Handle -> Handle -> IO ()
283readChunksOnException inh devNull =
284 let readEx = IUF.onException (\_ -> hClose inh) FH.chunkReader
285 in IUF.fold (IFH.writeChunks devNull) readEx inh
288inspect $ hasNoTypeClasses 'readChunksOnException
291-- | Send the file contents to /dev/null with exception handling
292readChunksBracket_ :: Handle -> Handle -> IO ()
293readChunksBracket_ inh devNull =
294 let readEx = IUF.bracket_ return (\_ -> hClose inh) FH.chunkReader
295 in IUF.fold (IFH.writeChunks devNull) readEx inh
298inspect $ hasNoTypeClasses 'readChunksBracket_
301readChunksBracket :: Handle -> Handle -> IO ()
302readChunksBracket inh devNull =
303 let readEx = IUF.bracket return (\_ -> hClose inh) FH.chunkReader
304 in IUF.fold (IFH.writeChunks devNull) readEx inh
306o_1_space_copy_exceptions_readChunks :: BenchEnv -> [Benchmark]
307o_1_space_copy_exceptions_readChunks env =
308 [ bgroup "exceptions/readChunks"
309 [ mkBench "UF.onException" env $ \inH _ ->
310 readChunksOnException inH (nullH env)
311 , mkBench "UF.bracket_" env $ \inH _ ->
312 readChunksBracket_ inH (nullH env)
313 , mkBench "UF.bracket" env $ \inH _ ->
314 readChunksBracket inH (nullH env)
318-------------------------------------------------------------------------------
319-- Exceptions toChunks
320-------------------------------------------------------------------------------
322-- | Send the file contents to /dev/null with exception handling
323toChunksBracket_ :: Handle -> Handle -> IO ()
324toChunksBracket_ inh devNull =
325 let readEx = bracketUnsafe
328 (\_ -> fromStreamD $ IFH.readChunks inh)
329 in Stream.fold (IFH.writeChunks devNull) readEx
332inspect $ hasNoTypeClasses 'toChunksBracket_
335toChunksBracket :: Handle -> Handle -> IO ()
336toChunksBracket inh devNull =
337 let readEx = Stream.bracket
340 (\_ -> fromStreamD $ IFH.readChunks inh)
341 in Stream.fold (IFH.writeChunks devNull) readEx
343o_1_space_copy_exceptions_toChunks :: BenchEnv -> [Benchmark]
344o_1_space_copy_exceptions_toChunks env =
345 [ bgroup "exceptions/toChunks"
346 [ mkBench "Stream.bracket_" env $ \inH _ ->
347 toChunksBracket_ inH (nullH env)
348 , mkBench "Stream.bracket" env $ \inH _ ->
349 toChunksBracket inH (nullH env)
353benchmarks :: String -> BenchEnv -> Int -> [Benchmark]
354benchmarks moduleName _env size =
355 [ bgroup (o_1_space_prefix moduleName) $ concat
356 [ o_1_space_serial_exceptions size
357 , o_1_space_copy_exceptions_readChunks _env
358 , o_1_space_copy_exceptions_toChunks _env
359 , 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