2-- Module : Streamly.Benchmark.Common.Handle
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
10{-# LANGUAGE ScopedTypeVariables #-}
12#ifdef __HADDOCK_VERSION__
17{-# LANGUAGE TemplateHaskell #-}
18{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
21module Streamly.Benchmark.Common.Handle
38import Control.DeepSeq (NFData(rnf))
39import Data.Char (ord, chr)
40#if MIN_VERSION_base(4,17,0)
41import Data.Char (generalCategory, GeneralCategory(Space))
43import Data.Word (Word8)
44import System.Directory (getFileSize)
45import System.Environment (lookupEnv)
46import System.IO (openFile, IOMode(..), Handle, hClose, stderr, hPutStrLn)
47import System.Process (callCommand)
50import Prelude hiding (last, length)
51import Test.Tasty.Bench hiding (env)
55scratchDir = "benchmark-tmp/"
58outfile = scratchDir ++ "out.txt"
61inFileSmall = scratchDir ++ "in-10MB.txt"
64inFileBig = scratchDir ++ "in-100MB.txt"
66data RefHandles = RefHandles
72data Handles = Handles !Handle !Handle
74instance NFData Handles where
77data BenchEnv = BenchEnv
78 { href :: IORef RefHandles
82 , smallInFile :: String
86withScaling :: BenchEnv -> String -> String
88 let factor = round (fromIntegral (bigSize env)
89 / (fromIntegral (smallSize env) :: Double)) :: Int
92 else str ++ " (1/" ++ show factor ++ ")"
94getHandles :: BenchEnv -> (RefHandles -> Handles) -> IO Handles
95getHandles env mkHandles = do
96 r <- readIORef $ href env
103 smallInHandle <- openFile (smallInFile env) ReadMode
104 bigInHandle <- openFile (bigInFile env) ReadMode
105 outHandle <- openFile outfile WriteMode
107 let refHandles = RefHandles
108 { smallInH = smallInHandle
109 , bigInH = bigInHandle
110 , outputH = outHandle
114 writeIORef (href env) refHandles
115 return $ mkHandles refHandles
119 => (RefHandles -> Handles)
122 -> (Handle -> Handle -> IO b)
124mkBenchCommon mkHandles name env action =
125 bench name $ nfIO $ do
126 -- XXX adds significant cpu time to the benchmarks
127 -- tasty-bench should provide a better way to do this
128 (Handles h1 h2) <- getHandles env mkHandles
132 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
133mkBench name env action = mkBenchCommon useBigH name env action
137 useBigH (RefHandles {bigInH = inh, outputH = outh}) = Handles inh outh
140 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
141mkBenchSmall name env action =
142 mkBenchCommon useSmallH (withScaling env name) env action
146 useSmallH (RefHandles {smallInH = inh, outputH = outh}) = Handles inh outh
148#if !MIN_VERSION_base(4,17,0)
149foreign import ccall unsafe "u_iswspace"
150 iswspace :: Int -> Int
153-- Code copied from base/Data.Char to INLINE it
154{-# INLINE isSpace #-}
155isSpace :: Char -> Bool
156-- isSpace includes non-breaking space
157-- The magic 0x377 isn't really that magical. As of 2014, all the codepoints
158-- at or below 0x377 have been assigned, so we shouldn't have to worry about
159-- any new spaces appearing below there. It would probably be best to
160-- use branchless ||, but currently the eqLit transformation will undo that,
161-- so we'll do it like this until there's a way around that.
163 | uc <= 0x377 = uc == 32 || uc - 0x9 <= 4 || uc == 0xa0
164#if MIN_VERSION_base(4,17,0)
165 | otherwise = generalCategory c == Space
167 | otherwise = iswspace (ord c) /= 0
170 uc = fromIntegral (ord c) :: Word
174isSp = isSpace . chr . fromIntegral
177smallFileSize = 10 * 1024 * 1024
180bigFileSize = 100 * 1024 * 1024
182mkHandleBenchEnv :: IO BenchEnv
184 r <- lookupEnv "Benchmark_FileSystem_Handle_InputFile"
187 Just inFileName -> return (inFileName, inFileName)
189 -- XXX will this work on windows/msys?
190 let cmd infile size =
191 "mkdir -p " ++ scratchDir
192 ++ "; test -e " ++ infile
193 ++ " || { echo \"creating input file " ++ infile
194 ++ "\" && head -c " ++ show size
195 ++ " </dev/urandom >" ++ infile
197 callCommand (cmd inFileSmall smallFileSize)
198 callCommand (cmd inFileBig bigFileSize)
199 return (inFileSmall, inFileBig)
201 hPutStrLn stderr $ "Using small input file: " ++ small
202 smallHandle <- openFile small ReadMode
204 hPutStrLn stderr $ "Using big input file: " ++ big
205 bigHandle <- openFile big ReadMode
207 hPutStrLn stderr $ "Using output file: " ++ outfile
208 outHandle <- openFile outfile WriteMode
209 devNull <- openFile "/dev/null" WriteMode
211 ssize <- fromIntegral <$> getFileSize small
212 bsize <- fromIntegral <$> getFileSize big
214 ref <- newIORef $ RefHandles
215 { smallInH = smallHandle
217 , outputH = outHandle
225 , smallInFile = small
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