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
54import Control.Monad.Catch (MonadCatch)
57import qualified Streamly.Internal.Data.Stream as D
61type Stream = Stream.SerialT
62toStreamD = Stream.toStream
63fromStreamD = Stream.fromStream
65type Stream = Stream.Stream
72afterUnsafe :: IO b -> Stream IO a -> Stream IO a
73finallyUnsafe :: IO b -> Stream IO a -> Stream IO a
74bracketUnsafe :: IO b -> (b -> IO c) -> (b -> Stream IO a) -> Stream IO a
76afterUnsafe = Stream.after_
77finallyUnsafe = Stream.finally_
78bracketUnsafe = Stream.bracket_
80afterUnsafe = Stream.afterUnsafe
81finallyUnsafe = Stream.finallyUnsafe
82bracketUnsafe = Stream.bracketUnsafe
85-------------------------------------------------------------------------------
87-------------------------------------------------------------------------------
92 deriving (Show, Eq, Ord)
94instance Exception BenchException
96retryNoneSimple :: Int -> Int -> IO ()
97retryNoneSimple length from =
100 (Map.singleton BenchException1 length)
106 source = Stream.enumerateFromTo from (from + length)
108retryNone :: Int -> Int -> IO ()
109retryNone length from = do
110 ref <- Ref.newIORef (0 :: Int)
112 $ Stream.retry (Map.singleton BenchException1 length) (const Stream.nil)
118 Stream.replicateM (from + length)
119 $ Ref.modifyIORef' ref (+ 1) >> Ref.readIORef ref
121retryAll :: Int -> Int -> IO ()
122retryAll length from = do
123 ref <- Ref.newIORef 0
126 (Map.singleton BenchException1 (length + from)) (const Stream.nil)
134 Ref.modifyIORef' ref (+ 1)
135 val <- Ref.readIORef ref
138 else throwIO BenchException1
140retryUnknown :: Int -> Int -> IO ()
141retryUnknown length from = do
143 $ Stream.retry (Map.singleton BenchException1 length) (const source)
144 $ throwIO BenchException2 `Stream.before` Stream.nil
148 source = Stream.enumerateFromTo from (from + length)
151o_1_space_serial_exceptions :: Int -> [Benchmark]
152o_1_space_serial_exceptions length =
155 [ benchIOSrc1 "retryNoneSimple" (retryNoneSimple length)
156 , benchIOSrc1 "retryNone" (retryNone length)
157 , benchIOSrc1 "retryAll" (retryAll length)
158 , benchIOSrc1 "retryUnknown" (retryUnknown length)
162-- XXX Move these to FileSystem.Handle benchmarks
164-------------------------------------------------------------------------------
165-- copy stream exceptions
166-------------------------------------------------------------------------------
168-- | Send the file contents to /dev/null with exception handling
169readWriteOnExceptionStream :: Handle -> Handle -> IO ()
170readWriteOnExceptionStream inh devNull =
171 let readEx = Stream.onException (hClose inh) (Stream.unfold FH.reader inh)
172 in Stream.fold (FH.write devNull) readEx
175inspect $ hasNoTypeClasses 'readWriteOnExceptionStream
178-- | Send the file contents to /dev/null with exception handling
179readWriteHandleExceptionStream :: Handle -> Handle -> IO ()
180readWriteHandleExceptionStream inh devNull =
181 let handler (_e :: SomeException) =
182 return $ Stream.fromEffect (hClose inh >> return 10)
183 readEx = Stream.handle handler (Stream.unfold FH.reader inh)
184 in Stream.fold (FH.write devNull) readEx
187inspect $ hasNoTypeClasses 'readWriteHandleExceptionStream
190-- | Send the file contents to /dev/null with exception handling
191readWriteFinally_Stream :: Handle -> Handle -> IO ()
192readWriteFinally_Stream inh devNull =
194 finallyUnsafe (hClose inh) (Stream.unfold FH.reader inh)
195 in Stream.fold (FH.write devNull) readEx
198inspect $ hasNoTypeClasses 'readWriteFinally_Stream
201readWriteFinallyStream :: Handle -> Handle -> IO ()
202readWriteFinallyStream inh devNull =
203 let readEx = Stream.finally (hClose inh) (Stream.unfold FH.reader inh)
204 in Stream.fold (FH.write devNull) readEx
206-- | Send the file contents to /dev/null with exception handling
207fromToBytesBracket_Stream :: Handle -> Handle -> IO ()
208fromToBytesBracket_Stream inh devNull =
209 let readEx = bracketUnsafe (return ()) (\_ -> hClose inh)
210 (\_ -> fromStreamD $ IFH.read inh)
211 in IFH.putBytes devNull (toStreamD readEx)
214inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
217fromToBytesBracketStream :: Handle -> Handle -> IO ()
218fromToBytesBracketStream inh devNull =
219 let readEx = Stream.bracket (return ()) (\_ -> hClose inh)
220 (\_ -> fromStreamD $ IFH.read inh)
221 in IFH.putBytes devNull (toStreamD readEx)
223readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
224readWriteBeforeAfterStream inh devNull =
226 Stream.after (hClose inh)
227 $ Stream.before (hPutChar devNull 'A') (Stream.unfold FH.reader inh)
228 in Stream.fold (FH.write devNull) readEx
231inspect $ 'readWriteBeforeAfterStream `hasNoType` ''D.Step
234readWriteAfterStream :: Handle -> Handle -> IO ()
235readWriteAfterStream inh devNull =
236 let readEx = Stream.after (hClose inh) (Stream.unfold FH.reader inh)
237 in Stream.fold (FH.write devNull) readEx
240inspect $ 'readWriteAfterStream `hasNoType` ''D.Step
243readWriteAfter_Stream :: Handle -> Handle -> IO ()
244readWriteAfter_Stream inh devNull =
245 let readEx = afterUnsafe (hClose inh) (Stream.unfold FH.reader inh)
246 in Stream.fold (FH.write devNull) readEx
249inspect $ hasNoTypeClasses 'readWriteAfter_Stream
250inspect $ 'readWriteAfter_Stream `hasNoType` ''D.Step
253o_1_space_copy_stream_exceptions :: BenchEnv -> [Benchmark]
254o_1_space_copy_stream_exceptions env =
255 [ bgroup "exceptions"
256 [ mkBenchSmall "Stream.onException" env $ \inh _ ->
257 readWriteOnExceptionStream inh (nullH env)
258 , mkBenchSmall "Stream.handle" env $ \inh _ ->
259 readWriteHandleExceptionStream inh (nullH env)
260 , mkBenchSmall "Stream.finally_" env $ \inh _ ->
261 readWriteFinally_Stream inh (nullH env)
262 , mkBenchSmall "Stream.finally" env $ \inh _ ->
263 readWriteFinallyStream inh (nullH env)
264 , mkBenchSmall "Stream.after . Stream.before" env $ \inh _ ->
265 readWriteBeforeAfterStream inh (nullH env)
266 , mkBenchSmall "Stream.after" env $ \inh _ ->
267 readWriteAfterStream inh (nullH env)
268 , mkBenchSmall "Stream.after_" env $ \inh _ ->
269 readWriteAfter_Stream inh (nullH env)
271 , bgroup "exceptions/fromToBytes"
272 [ mkBenchSmall "Stream.bracket_" env $ \inh _ ->
273 fromToBytesBracket_Stream inh (nullH env)
274 , mkBenchSmall "Stream.bracket" env $ \inh _ ->
275 fromToBytesBracketStream inh (nullH env)
279 -------------------------------------------------------------------------------
280-- Exceptions readChunks
281-------------------------------------------------------------------------------
283-- | Send the file contents to /dev/null with exception handling
284readChunksOnException :: Handle -> Handle -> IO ()
285readChunksOnException inh devNull =
286 let readEx = IUF.onException (\_ -> hClose inh) FH.chunkReader
287 in IUF.fold (IFH.writeChunks devNull) readEx inh
290#if __GLASGOW_HASKELL__ >= 906
291inspect $ hasNoTypeClassesExcept 'readChunksOnException [''MonadCatch]
293inspect $ hasNoTypeClasses 'readChunksOnException
297-- | Send the file contents to /dev/null with exception handling
298readChunksBracket_ :: Handle -> Handle -> IO ()
299readChunksBracket_ inh devNull =
300 let readEx = IUF.bracket_ return (\_ -> hClose inh) FH.chunkReader
301 in IUF.fold (IFH.writeChunks devNull) readEx inh
304#if __GLASGOW_HASKELL__ >= 906
305inspect $ hasNoTypeClassesExcept 'readChunksBracket_ [''MonadCatch]
307inspect $ hasNoTypeClasses 'readChunksBracket_
311readChunksBracket :: Handle -> Handle -> IO ()
312readChunksBracket inh devNull =
313 let readEx = IUF.bracket return (\_ -> hClose inh) FH.chunkReader
314 in IUF.fold (IFH.writeChunks devNull) readEx inh
316o_1_space_copy_exceptions_readChunks :: BenchEnv -> [Benchmark]
317o_1_space_copy_exceptions_readChunks env =
318 [ bgroup "exceptions/readChunks"
319 [ mkBench "UF.onException" env $ \inH _ ->
320 readChunksOnException inH (nullH env)
321 , mkBench "UF.bracket_" env $ \inH _ ->
322 readChunksBracket_ inH (nullH env)
323 , mkBench "UF.bracket" env $ \inH _ ->
324 readChunksBracket inH (nullH env)
328-------------------------------------------------------------------------------
329-- Exceptions toChunks
330-------------------------------------------------------------------------------
332-- | Send the file contents to /dev/null with exception handling
333toChunksBracket_ :: Handle -> Handle -> IO ()
334toChunksBracket_ inh devNull =
335 let readEx = bracketUnsafe
338 (\_ -> fromStreamD $ IFH.readChunks inh)
339 in Stream.fold (IFH.writeChunks devNull) readEx
342inspect $ hasNoTypeClasses 'toChunksBracket_
345toChunksBracket :: Handle -> Handle -> IO ()
346toChunksBracket inh devNull =
347 let readEx = Stream.bracket
350 (\_ -> fromStreamD $ IFH.readChunks inh)
351 in Stream.fold (IFH.writeChunks devNull) readEx
353o_1_space_copy_exceptions_toChunks :: BenchEnv -> [Benchmark]
354o_1_space_copy_exceptions_toChunks env =
355 [ bgroup "exceptions/toChunks"
356 [ mkBench "Stream.bracket_" env $ \inH _ ->
357 toChunksBracket_ inH (nullH env)
358 , mkBench "Stream.bracket" env $ \inH _ ->
359 toChunksBracket inH (nullH env)
363benchmarks :: String -> BenchEnv -> Int -> [Benchmark]
364benchmarks moduleName _env size =
365 [ bgroup (o_1_space_prefix moduleName) $ concat
366 [ o_1_space_serial_exceptions size
367 , o_1_space_copy_exceptions_readChunks _env
368 , o_1_space_copy_exceptions_toChunks _env
369 , 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