on 33e6fd0 help sign in
streamly/benchmark/FileIO.hs
296 lines 12 kB history raw
1-- |
2-- Module : Main
3-- Copyright : (c) 2019 Harendra Kumar
4--
5-- License : BSD3
6-- Maintainer : harendra.kumar@gmail.com
8{-# LANGUAGE CPP #-}
10import Control.DeepSeq (NFData)
11import System.IO (openFile, IOMode(..), Handle, hClose)
12import System.Process.Typed (shell, runProcess_)
14import Data.IORef
15import Gauge
17import qualified Streamly.Benchmark.FileIO.Stream as BFS
18import qualified Streamly.Benchmark.FileIO.Array as BFA
20-- Input and output file handles
21data Handles = Handles Handle Handle
23scratchDir :: String
24scratchDir = "benchmark/scratch/"
26outfile :: String
27outfile = scratchDir ++ "out.txt"
29blockSize, blockCount :: Int
30blockSize = 32768
31blockCount = 3200
33#ifdef DEVBUILD
34-- This is a 500MB text file for text processing benchmarks. We cannot
35-- have it in the repo, therefore we use it locally with DEVBUILD
36-- conditional (enabled by "dev" cabal flag). Some tests that depend on
37-- this file are available only in DEVBUILD mode.
38infile :: String
39infile = "benchmark/text-processing/gutenberg-500.txt"
41fileSize :: Int
42fileSize = blockSize * blockCount
44#else
45infile :: String
46infile = scratchDir ++ "in-100MB.txt"
47#endif
49main :: IO ()
50main = do
51#ifndef DEVBUILD
52 -- XXX will this work on windows/msys?
53 let cmd = "mkdir -p " ++ scratchDir
54 ++ "; test -e " ++ infile
55 ++ " || { echo \"creating input file " ++ infile
56 ++ "\" && dd if=/dev/random of=" ++ infile
57 ++ " bs=" ++ show blockSize
58 ++ " count=" ++ show blockCount
59 ++ ";}"
61 runProcess_ (shell cmd)
62#endif
63 inHandle <- openFile infile ReadMode
64 outHandle <- openFile outfile WriteMode
65 href <- newIORef $ Handles inHandle outHandle
66 devNull <- openFile "/dev/null" WriteMode
68 defaultMain
69 [ bgroup "readArray"
70 [ mkBench "last" href $ do
71 Handles inh _ <- readIORef href
72 BFA.last inh
73 -- Note: this cannot be fairly compared with GNU wc -c or wc -m as
74 -- wc uses lseek to just determine the file size rather than reading
75 -- and counting characters.
76 , mkBench "length (bytecount)" href $ do
77 Handles inh _ <- readIORef href
78 BFA.countBytes inh
79 , mkBench "linecount" href $ do
80 Handles inh _ <- readIORef href
81 BFA.countLines inh
82 , mkBench "wordcount" href $ do
83 Handles inh _ <- readIORef href
84 BFA.countWords inh
85 , mkBench "sum" href $ do
86 Handles inh _ <- readIORef href
87 BFA.sumBytes inh
88 , mkBench "cat" href $ do
89 Handles inh _ <- readIORef href
90 BFA.cat devNull inh
91 , mkBench "catBracket" href $ do
92 Handles inh _ <- readIORef href
93 BFA.catBracket devNull inh
94 , mkBench "catBracketStream" href $ do
95 Handles inh _ <- readIORef href
96 BFA.catBracketStream devNull inh
97 , mkBench "catOnException" href $ do
98 Handles inh _ <- readIORef href
99 BFA.catOnException devNull inh
100 , mkBench "read-utf8" href $ do
101 Handles inh _ <- readIORef href
102 BFA.decodeUtf8Lenient inh
103 ]
104 , bgroup "readStream"
105 [ mkBench "last" href $ do
106 Handles inh _ <- readIORef href
107 BFS.last inh
108 , mkBench "length (bytecount)" href $ do
109 Handles inh _ <- readIORef href
110 BFS.countBytes inh
111 , mkBench "linecount" href $ do
112 Handles inh _ <- readIORef href
113 BFS.countLines inh
114 , mkBench "linecountU" href $ do
115 Handles inh _ <- readIORef href
116 BFS.countLinesU inh
117 , mkBench "wordcount" href $ do
118 Handles inh _ <- readIORef href
119 BFS.countWords inh
120 , mkBench "sum" href $ do
121 Handles inh _ <- readIORef href
122 BFS.sumBytes inh
123 , mkBench "cat" href $ do
124 Handles inh _ <- readIORef href
125 BFS.cat devNull inh
126 , mkBench "catStream" href $ do
127 Handles inh _ <- readIORef href
128 BFS.catStreamWrite devNull inh
129#ifdef DEVBUILD
130 , mkBench "catOnException" href $ do
131 Handles inh _ <- readIORef href
132 BFS.catOnException devNull inh
133 , mkBench "catHandle" href $ do
134 Handles inh _ <- readIORef href
135 BFS.catHandle devNull inh
136 , mkBench "catFinally" href $ do
137 Handles inh _ <- readIORef href
138 BFS.catFinally devNull inh
139 , mkBench "catBracketStream" href $ do
140 Handles inh _ <- readIORef href
141 BFS.catBracketStream devNull inh
142 , mkBench "catBracket" href $ do
143 Handles inh _ <- readIORef href
144 BFS.catBracket devNull inh
145#endif
146 , mkBench "read-word8" href $ do
147 Handles inh _ <- readIORef href
148 BFS.readWord8 inh
149 , mkBench "read-char8" href $ do
150 Handles inh _ <- readIORef href
151 BFS.decodeChar8 inh
152 , mkBench "read-utf8" href $ do
153 Handles inh _ <- readIORef href
154 BFS.decodeUtf8Lenient inh
155 ]
156 , bgroup "copyArray"
157 [ mkBench "copy" href $ do
158 Handles inh outh <- readIORef href
159 BFA.copy inh outh
160 ]
161#ifdef DEVBUILD
162 -- This takes a little longer therefore put under the dev conditional
163 , bgroup "copyStream"
164 [ mkBench "fromToHandle" href $ do
165 Handles inh outh <- readIORef href
166 BFS.copy inh outh
167 ]
168 -- This needs an ascii file, as decode just errors out.
169 , bgroup "decode-encode"
170 [ mkBench "char8" href $ do
171 Handles inh outh <- readIORef href
172 BFS.copyCodecChar8 inh outh
173 , mkBench "utf8-arrays" href $ do
174 Handles inh outh <- readIORef href
175 BFA.copyCodecUtf8Lenient inh outh
176 , mkBench "utf8" href $ do
177 Handles inh outh <- readIORef href
178 BFS.copyCodecUtf8Lenient inh outh
179 ]
180 , bgroup "grouping"
181 [ mkBench "chunksOf (single chunk)" href $ do
182 Handles inh _ <- readIORef href
183 BFS.chunksOf fileSize inh
185 , mkBench "chunksOf 1" href $ do
186 Handles inh _ <- readIORef href
187 BFS.chunksOf 1 inh
188 , mkBench "chunksOf 10" href $ do
189 Handles inh _ <- readIORef href
190 BFS.chunksOf 10 inh
191 , mkBench "chunksOf 1000" href $ do
192 Handles inh _ <- readIORef href
193 BFS.chunksOf 1000 inh
194 ]
195 , bgroup "group-ungroup"
196 [ mkBench "lines-unlines" href $ do
197 Handles inh outh <- readIORef href
198 BFS.linesUnlinesCopy inh outh
199 , mkBench "lines-unlines-arrays" href $ do
200 Handles inh outh <- readIORef href
201 BFA.linesUnlinesCopy inh outh
202 , mkBench "words-unwords" href $ do
203 Handles inh outh <- readIORef href
204 BFS.wordsUnwordsCopy inh outh
205 , mkBench "words-unwords-word8" href $ do
206 Handles inh outh <- readIORef href
207 BFS.wordsUnwordsCopyWord8 inh outh
208 , mkBench "words-unwords-arrays" href $ do
209 Handles inh outh <- readIORef href
210 BFA.wordsUnwordsCopy inh outh
211 ]
213 , bgroup "splitting"
214 [ bgroup "predicate"
215 [ mkBench "splitOn \\n (line count)" href $ do
216 Handles inh _ <- readIORef href
217 BFS.splitOn inh
218 , mkBench "splitOnSuffix \\n (line count)" href $ do
219 Handles inh _ <- readIORef href
220 BFS.splitOnSuffix inh
221 , mkBench "wordsBy isSpace (word count)" href $ do
222 Handles inh _ <- readIORef href
223 BFS.wordsBy inh
224 ]
226 , bgroup "empty-pattern"
227 [ mkBench "splitOnSeq \"\"" href $ do
228 Handles inh _ <- readIORef href
229 BFS.splitOnSeq "" inh
230 , mkBench "splitOnSuffixSeq \"\"" href $ do
231 Handles inh _ <- readIORef href
232 BFS.splitOnSuffixSeq "" inh
233 ]
234 , bgroup "short-pattern"
235 [ mkBench "splitOnSeq \\n (line count)" href $ do
236 Handles inh _ <- readIORef href
237 BFS.splitOnSeq "\n" inh
238 , mkBench "splitOnSuffixSeq \\n (line count)" href $ do
239 Handles inh _ <- readIORef href
240 BFS.splitOnSuffixSeq "\n" inh
241 , mkBench "splitOnSeq a" href $ do
242 Handles inh _ <- readIORef href
243 BFS.splitOnSeq "a" inh
244 , mkBench "splitOnSeq \\r\\n" href $ do
245 Handles inh _ <- readIORef href
246 BFS.splitOnSeq "\r\n" inh
247 , mkBench "splitOnSuffixSeq \\r\\n)" href $ do
248 Handles inh _ <- readIORef href
249 BFS.splitOnSuffixSeq "\r\n" inh
250 , mkBench "splitOnSeq aa" href $ do
251 Handles inh _ <- readIORef href
252 BFS.splitOnSeq "aa" inh
253 , mkBench "splitOnSeq aaaa" href $ do
254 Handles inh _ <- readIORef href
255 BFS.splitOnSeq "aaaa" inh
256 , mkBench "splitOnSeq abcdefgh" href $ do
257 Handles inh _ <- readIORef href
258 BFS.splitOnSeq "abcdefgh" inh
259 , mkBench "splitOnSeqUtf8 abcdefgh" href $ do
260 Handles inh _ <- readIORef href
261 BFS.splitOnSeqUtf8 "abcdefgh" inh
262 ]
263 , bgroup "long-pattern"
264 [ mkBench "splitOnSeq abcdefghi" href $ do
265 Handles inh _ <- readIORef href
266 BFS.splitOnSeq "abcdefghi" inh
267 , mkBench "splitOnSeq catcatcatcatcat" href $ do
268 Handles inh _ <- readIORef href
269 BFS.splitOnSeq "catcatcatcatcat" inh
270 , mkBench "splitOnSeq abc...xyz" href $ do
271 Handles inh _ <- readIORef href
272 BFS.splitOnSeq "abcdefghijklmnopqrstuvwxyz" inh
273 , mkBench "splitOnSuffixSeq abc...xyz" href $ do
274 Handles inh _ <- readIORef href
275 BFS.splitOnSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
276 , mkBench "splitOnSeqUtf8 abc...xyz" href $ do
277 Handles inh _ <- readIORef href
278 BFS.splitOnSeqUtf8 "abcdefghijklmnopqrstuvwxyz" inh
279 ]
280 ]
281#endif
282 ]
284 where
286 mkBench :: NFData b => String -> IORef Handles -> IO b -> Benchmark
287 mkBench name ref action =
288 bench name $ perRunEnv (do
289 (Handles inh outh) <- readIORef ref
290 hClose inh
291 hClose outh
292 inHandle <- openFile infile ReadMode
293 outHandle <- openFile outfile WriteMode
294 writeIORef ref (Handles inHandle outHandle)
295 )
296 (\_ -> action)