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
36import Control.DeepSeq (NFData(rnf))
37import Data.Char (ord, chr)
38#if MIN_VERSION_base(4,17,0)
39import Data.Char (generalCategory, GeneralCategory(Space))
41import Data.Word (Word8)
42import System.Directory (getFileSize)
43import System.Environment (lookupEnv)
44import System.IO (openFile, IOMode(..), Handle, hClose, stderr, hPutStrLn)
45import System.Process (callCommand)
48import Prelude hiding (last, length)
49import Gauge hiding (env)
53scratchDir = "benchmark-tmp/"
56outfile = scratchDir ++ "out.txt"
59inFileSmall = scratchDir ++ "in-10MB.txt"
62inFileBig = scratchDir ++ "in-100MB.txt"
64data RefHandles = RefHandles
70data Handles = Handles !Handle !Handle
72instance NFData Handles where
75data BenchEnv = BenchEnv
76 { href :: IORef RefHandles
80 , smallInFile :: String
84withScaling :: BenchEnv -> String -> String
86 let factor = round (fromIntegral (bigSize env)
87 / (fromIntegral (smallSize env) :: Double)) :: Int
90 else str ++ " (1/" ++ show factor ++ ")"
92getHandles :: BenchEnv -> (RefHandles -> Handles) -> IO Handles
93getHandles env mkHandles = do
94 r <- readIORef $ href env
101 smallInHandle <- openFile (smallInFile env) ReadMode
102 bigInHandle <- openFile (bigInFile env) ReadMode
103 outHandle <- openFile outfile WriteMode
105 let refHandles = RefHandles
106 { smallInH = smallInHandle
107 , bigInH = bigInHandle
108 , outputH = outHandle
112 writeIORef (href env) refHandles
113 return $ mkHandles refHandles
117 => (RefHandles -> Handles)
120 -> (Handle -> Handle -> IO b)
122mkBenchCommon mkHandles name env action =
123 bench name $ nfIO $ do
124 -- XXX adds significant cpu time to the benchmarks
125 -- tasty-bench should provide a better way to do this
126 (Handles h1 h2) <- getHandles env mkHandles
130 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
131mkBench name env action = mkBenchCommon useBigH name env action
135 useBigH (RefHandles {bigInH = inh, outputH = outh}) = Handles inh outh
138 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
139mkBenchSmall name env action =
140 mkBenchCommon useSmallH (withScaling env name) env action
144 useSmallH (RefHandles {smallInH = inh, outputH = outh}) = Handles inh outh
146#if !MIN_VERSION_base(4,17,0)
147foreign import ccall unsafe "u_iswspace"
148 iswspace :: Int -> Int
151-- Code copied from base/Data.Char to INLINE it
152{-# INLINE isSpace #-}
153isSpace :: Char -> Bool
154-- isSpace includes non-breaking space
155-- The magic 0x377 isn't really that magical. As of 2014, all the codepoints
156-- at or below 0x377 have been assigned, so we shouldn't have to worry about
157-- any new spaces appearing below there. It would probably be best to
158-- use branchless ||, but currently the eqLit transformation will undo that,
159-- so we'll do it like this until there's a way around that.
161 | uc <= 0x377 = uc == 32 || uc - 0x9 <= 4 || uc == 0xa0
162#if MIN_VERSION_base(4,17,0)
163 | otherwise = generalCategory c == Space
165 | otherwise = iswspace (ord c) /= 0
168 uc = fromIntegral (ord c) :: Word
172isSp = isSpace . chr . fromIntegral
175smallFileSize = 10 * 1024 * 1024
178bigFileSize = 100 * 1024 * 1024
180mkHandleBenchEnv :: IO BenchEnv
182 r <- lookupEnv "Benchmark_FileSystem_Handle_InputFile"
185 Just inFileName -> return (inFileName, inFileName)
187 -- XXX will this work on windows/msys?
188 let cmd infile size =
189 "mkdir -p " ++ scratchDir
190 ++ "; test -e " ++ infile
191 ++ " || { echo \"creating input file " ++ infile
192 ++ "\" && head -c " ++ show size
193 ++ " </dev/urandom >" ++ infile
195 callCommand (cmd inFileSmall smallFileSize)
196 callCommand (cmd inFileBig bigFileSize)
197 return (inFileSmall, inFileBig)
199 hPutStrLn stderr $ "Using small input file: " ++ small
200 smallHandle <- openFile small ReadMode
202 hPutStrLn stderr $ "Using big input file: " ++ big
203 bigHandle <- openFile big ReadMode
205 hPutStrLn stderr $ "Using output file: " ++ outfile
206 outHandle <- openFile outfile WriteMode
207 devNull <- openFile "/dev/null" WriteMode
209 ssize <- fromIntegral <$> getFileSize small
210 bsize <- fromIntegral <$> getFileSize big
212 ref <- newIORef $ RefHandles
213 { smallInH = smallHandle
215 , outputH = outHandle
223 , 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