on b339cf8 help sign in
154 lines 4.0 kB history raw
1-- |
2-- Module : Streamly.Benchmark.FileSystem.Handle
3-- Copyright : (c) 2019 Composewell Technologies
4--
5-- License : BSD3
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
10{-# LANGUAGE CPP #-}
11{-# LANGUAGE ScopedTypeVariables #-}
13#ifdef __HADDOCK_VERSION__
14#undef INSPECTION
15#endif
17#ifdef INSPECTION
18{-# LANGUAGE TemplateHaskell #-}
19{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
20#endif
22module Handle.Common
23 ( BenchEnv (..)
24 , RefHandles (..)
25 , scratchDir
26 , inFileSmall
27 , inFileBig
28 , outfile
29 , mkBench
30 , mkBenchSmall
31 , isSpace
32 , isSp
33 )
34where
36import Control.DeepSeq (NFData(rnf))
37import Data.Char (ord, chr)
38import Data.Word (Word8)
39import System.IO (openFile, IOMode(..), Handle, hClose)
41import Data.IORef
42import Gauge hiding (env)
44scratchDir :: String
45scratchDir = "benchmark-tmp/"
47outfile :: String
48outfile = scratchDir ++ "out.txt"
50inFileSmall :: String
51inFileSmall = scratchDir ++ "in-10MB.txt"
53inFileBig :: String
54inFileBig = scratchDir ++ "in-100MB.txt"
56data RefHandles = RefHandles
57 { smallInH :: Handle
58 , bigInH :: Handle
59 , outputH :: Handle
60 }
62data Handles = Handles !Handle !Handle
64instance NFData Handles where
65 rnf _ = ()
67data BenchEnv = BenchEnv
68 { href :: IORef RefHandles
69 , smallSize :: Int
70 , bigSize :: Int
71 , nullH :: Handle
72 , smallInFile :: String
73 , bigInFile :: String
74 }
76withScaling :: BenchEnv -> String -> String
77withScaling env str =
78 let factor = round (fromIntegral (bigSize env)
79 / (fromIntegral (smallSize env) :: Double)) :: Int
80 in if factor == 1
81 then str
82 else str ++ " (1/" ++ show factor ++ ")"
84mkBenchCommon ::
85 NFData b
86 => (RefHandles -> Handles)
87 -> String
88 -> BenchEnv
89 -> (Handle -> Handle -> IO b)
90 -> Benchmark
91mkBenchCommon mkHandles name env action =
92 bench name $ perRunEnv (do
93 r <- readIORef $ href env
95 -- close old handles
96 hClose $ smallInH r
97 hClose $ bigInH r
98 hClose $ outputH r
100 -- reopen
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
109 }
111 -- update
112 writeIORef (href env) $ refHandles
113 return $ mkHandles refHandles
114 )
115 (\(Handles h1 h2) -> action h1 h2)
117mkBench ::
118 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
119mkBench name env action = mkBenchCommon useBigH name env action
121 where
123 useBigH (RefHandles {bigInH = inh, outputH = outh}) = Handles inh outh
125mkBenchSmall ::
126 NFData b => String -> BenchEnv -> (Handle -> Handle -> IO b) -> Benchmark
127mkBenchSmall name env action =
128 mkBenchCommon useSmallH (withScaling env name) env action
130 where
132 useSmallH (RefHandles {smallInH = inh, outputH = outh}) = Handles inh outh
134foreign import ccall unsafe "u_iswspace"
135 iswspace :: Int -> Int
137-- Code copied from base/Data.Char to INLINE it
138{-# INLINE isSpace #-}
139isSpace :: Char -> Bool
140-- isSpace includes non-breaking space
141-- The magic 0x377 isn't really that magical. As of 2014, all the codepoints
142-- at or below 0x377 have been assigned, so we shouldn't have to worry about
143-- any new spaces appearing below there. It would probably be best to
144-- use branchless ||, but currently the eqLit transformation will undo that,
145-- so we'll do it like this until there's a way around that.
146isSpace c
147 | uc <= 0x377 = uc == 32 || uc - 0x9 <= 4 || uc == 0xa0
148 | otherwise = iswspace (ord c) /= 0
149 where
150 uc = fromIntegral (ord c) :: Word
152{-# INLINE isSp #-}
153isSp :: Word8 -> Bool
154isSp = isSpace . chr . fromIntegral