on 511fe85 help sign in
streamly/benchmark/FileIO.hs
317 lines 13 kB history raw
1-- |
2-- Module : Main
3-- Copyright : (c) 2019 Harendra Kumar
4--
5-- License : BSD3
6-- Maintainer : streamly@composewell.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 "catOnExceptionStream" href $ do
134 Handles inh _ <- readIORef href
135 BFS.catOnExceptionStream devNull inh
136 , mkBench "catHandle" href $ do
137 Handles inh _ <- readIORef href
138 BFS.catHandle devNull inh
139 , mkBench "catHandleStream" href $ do
140 Handles inh _ <- readIORef href
141 BFS.catHandleStream devNull inh
142 , mkBench "catFinally" href $ do
143 Handles inh _ <- readIORef href
144 BFS.catFinally devNull inh
145 , mkBench "catFinallyStream" href $ do
146 Handles inh _ <- readIORef href
147 BFS.catFinallyStream devNull inh
148 , mkBench "catBracketStream" href $ do
149 Handles inh _ <- readIORef href
150 BFS.catBracketStream devNull inh
151 , mkBench "catBracket" href $ do
152 Handles inh _ <- readIORef href
153 BFS.catBracket devNull inh
154#endif
155 , mkBench "read-word8" href $ do
156 Handles inh _ <- readIORef href
157 BFS.readWord8 inh
158 , mkBench "read-latin1" href $ do
159 Handles inh _ <- readIORef href
160 BFS.decodeLatin1 inh
161 , mkBench "read-utf8" href $ do
162 Handles inh _ <- readIORef href
163 BFS.decodeUtf8Lax inh
164 ]
165 , bgroup "copyArray"
166 [ mkBench "copy" href $ do
167 Handles inh outh <- readIORef href
168 BFA.copy inh outh
169 ]
170#ifdef DEVBUILD
171 -- This takes a little longer therefore put under the dev conditional
172 , bgroup "copyStream"
173 [ mkBench "fromToHandle" href $ do
174 Handles inh outh <- readIORef href
175 BFS.copy inh outh
176 ]
177 -- This needs an ascii file, as decode just errors out.
178 , bgroup "decode-encode"
179 [ mkBench "latin1" href $ do
180 Handles inh outh <- readIORef href
181 BFS.copyCodecChar8 inh outh
182 , mkBench "utf8-arrays" href $ do
183 Handles inh outh <- readIORef href
184 BFA.copyCodecUtf8Lenient inh outh
185 , mkBench "utf8" href $ do
186 Handles inh outh <- readIORef href
187 BFS.copyCodecUtf8Lenient inh outh
188 ]
189 , bgroup "grouping"
190 [ mkBench "chunksOf (single chunk)" href $ do
191 Handles inh _ <- readIORef href
192 BFS.chunksOf fileSize inh
194 , mkBench "chunksOf 1" href $ do
195 Handles inh _ <- readIORef href
196 BFS.chunksOf 1 inh
197 , mkBench "chunksOf 10" href $ do
198 Handles inh _ <- readIORef href
199 BFS.chunksOf 10 inh
200 , mkBench "chunksOf 1000" href $ do
201 Handles inh _ <- readIORef href
202 BFS.chunksOf 1000 inh
203 ]
204 , bgroup "group-ungroup-stream"
205 [ mkBench "lines-unlines-[Char]" href $ do
206 Handles inh outh <- readIORef href
207 BFS.linesUnlinesCopy inh outh
208 , mkBench "lines-unlines-Word8Array" href $ do
209 Handles inh outh <- readIORef href
210 BFS.linesUnlinesArrayWord8Copy inh outh
211 , mkBench "lines-unlines-CharArray" href $ do
212 Handles inh outh <- readIORef href
213 BFS.linesUnlinesArrayCharCopy inh outh
214 , mkBench "words-unwords-[Word8]" href $ do
215 Handles inh outh <- readIORef href
216 BFS.wordsUnwordsCopyWord8 inh outh
217 , mkBench "words-unwords-[Char]" href $ do
218 Handles inh outh <- readIORef href
219 BFS.wordsUnwordsCopy inh outh
220 , mkBench "words-unwords-CharArray" href $ do
221 Handles inh outh <- readIORef href
222 BFS.wordsUnwordsCharArrayCopy inh outh
223 ]
225 , bgroup "group-ungroup-array-stream"
226 [ mkBench "lines-unlines-Word8Array" href $ do
227 Handles inh outh <- readIORef href
228 BFA.linesUnlinesCopy inh outh
229 , mkBench "words-unwords-Word8Array" href $ do
230 Handles inh outh <- readIORef href
231 BFA.wordsUnwordsCopy inh outh
232 ]
234 , bgroup "splitting"
235 [ bgroup "predicate"
236 [ mkBench "splitOn \\n (line count)" href $ do
237 Handles inh _ <- readIORef href
238 BFS.splitOn inh
239 , mkBench "splitOnSuffix \\n (line count)" href $ do
240 Handles inh _ <- readIORef href
241 BFS.splitOnSuffix inh
242 , mkBench "wordsBy isSpace (word count)" href $ do
243 Handles inh _ <- readIORef href
244 BFS.wordsBy inh
245 ]
247 , bgroup "empty-pattern"
248 [ mkBench "splitOnSeq \"\"" href $ do
249 Handles inh _ <- readIORef href
250 BFS.splitOnSeq "" inh
251 , mkBench "splitOnSuffixSeq \"\"" href $ do
252 Handles inh _ <- readIORef href
253 BFS.splitOnSuffixSeq "" inh
254 ]
255 , bgroup "short-pattern"
256 [ mkBench "splitOnSeq \\n (line count)" href $ do
257 Handles inh _ <- readIORef href
258 BFS.splitOnSeq "\n" inh
259 , mkBench "splitOnSuffixSeq \\n (line count)" href $ do
260 Handles inh _ <- readIORef href
261 BFS.splitOnSuffixSeq "\n" inh
262 , mkBench "splitOnSeq a" href $ do
263 Handles inh _ <- readIORef href
264 BFS.splitOnSeq "a" inh
265 , mkBench "splitOnSeq \\r\\n" href $ do
266 Handles inh _ <- readIORef href
267 BFS.splitOnSeq "\r\n" inh
268 , mkBench "splitOnSuffixSeq \\r\\n)" href $ do
269 Handles inh _ <- readIORef href
270 BFS.splitOnSuffixSeq "\r\n" inh
271 , mkBench "splitOnSeq aa" href $ do
272 Handles inh _ <- readIORef href
273 BFS.splitOnSeq "aa" inh
274 , mkBench "splitOnSeq aaaa" href $ do
275 Handles inh _ <- readIORef href
276 BFS.splitOnSeq "aaaa" inh
277 , mkBench "splitOnSeq abcdefgh" href $ do
278 Handles inh _ <- readIORef href
279 BFS.splitOnSeq "abcdefgh" inh
280 , mkBench "splitOnSeqUtf8 abcdefgh" href $ do
281 Handles inh _ <- readIORef href
282 BFS.splitOnSeqUtf8 "abcdefgh" inh
283 ]
284 , bgroup "long-pattern"
285 [ mkBench "splitOnSeq abcdefghi" href $ do
286 Handles inh _ <- readIORef href
287 BFS.splitOnSeq "abcdefghi" inh
288 , mkBench "splitOnSeq catcatcatcatcat" href $ do
289 Handles inh _ <- readIORef href
290 BFS.splitOnSeq "catcatcatcatcat" inh
291 , mkBench "splitOnSeq abc...xyz" href $ do
292 Handles inh _ <- readIORef href
293 BFS.splitOnSeq "abcdefghijklmnopqrstuvwxyz" inh
294 , mkBench "splitOnSuffixSeq abc...xyz" href $ do
295 Handles inh _ <- readIORef href
296 BFS.splitOnSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
297 , mkBench "splitOnSeqUtf8 abc...xyz" href $ do
298 Handles inh _ <- readIORef href
299 BFS.splitOnSeqUtf8 "abcdefghijklmnopqrstuvwxyz" inh
300 ]
301 ]
302#endif
303 ]
305 where
307 mkBench :: NFData b => String -> IORef Handles -> IO b -> Benchmark
308 mkBench name ref action =
309 bench name $ perRunEnv (do
310 (Handles inh outh) <- readIORef ref
311 hClose inh
312 hClose outh
313 inHandle <- openFile infile ReadMode
314 outHandle <- openFile outfile WriteMode
315 writeIORef ref (Handles inHandle outHandle)
316 )
317 (\_ -> action)