on e25db62 help sign in
streamly/benchmark/FileIO.hs
270 lines 11 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 "read-utf8" href $ do
92 Handles inh _ <- readIORef href
93 BFA.decodeUtf8Lenient inh
94 ]
95 , bgroup "readStream"
96 [ mkBench "last" href $ do
97 Handles inh _ <- readIORef href
98 BFS.last inh
99 , mkBench "length (bytecount)" href $ do
100 Handles inh _ <- readIORef href
101 BFS.countBytes inh
102 , mkBench "linecount" href $ do
103 Handles inh _ <- readIORef href
104 BFS.countLines inh
105 , mkBench "linecountU" href $ do
106 Handles inh _ <- readIORef href
107 BFS.countLinesU inh
108 , mkBench "wordcount" href $ do
109 Handles inh _ <- readIORef href
110 BFS.countWords inh
111 , mkBench "sum" href $ do
112 Handles inh _ <- readIORef href
113 BFS.sumBytes inh
114 , mkBench "cat" href $ do
115 Handles inh _ <- readIORef href
116 BFS.cat devNull inh
117 , mkBench "catStream" href $ do
118 Handles inh _ <- readIORef href
119 BFS.catStreamWrite devNull inh
120 , mkBench "read-word8" href $ do
121 Handles inh _ <- readIORef href
122 BFS.readWord8 inh
123 , mkBench "read-char8" href $ do
124 Handles inh _ <- readIORef href
125 BFS.decodeChar8 inh
126 , mkBench "read-utf8" href $ do
127 Handles inh _ <- readIORef href
128 BFS.decodeUtf8Lenient inh
129 ]
130 , bgroup "copyArray"
131 [ mkBench "copy" href $ do
132 Handles inh outh <- readIORef href
133 BFA.copy inh outh
134 ]
135#ifdef DEVBUILD
136 -- This takes a little longer therefore put under the dev conditional
137 , bgroup "copyStream"
138 [ mkBench "fromToHandle" href $ do
139 Handles inh outh <- readIORef href
140 BFS.copy inh outh
141 ]
142 -- This needs an ascii file, as decode just errors out.
143 , bgroup "decode-encode"
144 [ mkBench "char8" href $ do
145 Handles inh outh <- readIORef href
146 BFS.copyCodecChar8 inh outh
147 , mkBench "utf8-arrays" href $ do
148 Handles inh outh <- readIORef href
149 BFA.copyCodecUtf8Lenient inh outh
150 , mkBench "utf8" href $ do
151 Handles inh outh <- readIORef href
152 BFS.copyCodecUtf8Lenient inh outh
153 ]
154 , bgroup "grouping"
155 [ mkBench "chunksOf (single chunk)" href $ do
156 Handles inh _ <- readIORef href
157 BFS.chunksOf fileSize inh
159 , mkBench "chunksOf 1" href $ do
160 Handles inh _ <- readIORef href
161 BFS.chunksOf 1 inh
162 , mkBench "chunksOf 10" href $ do
163 Handles inh _ <- readIORef href
164 BFS.chunksOf 10 inh
165 , mkBench "chunksOf 1000" href $ do
166 Handles inh _ <- readIORef href
167 BFS.chunksOf 1000 inh
168 ]
169 , bgroup "group-ungroup"
170 [ mkBench "lines-unlines" href $ do
171 Handles inh outh <- readIORef href
172 BFS.linesUnlinesCopy inh outh
173 , mkBench "lines-unlines-arrays" href $ do
174 Handles inh outh <- readIORef href
175 BFA.linesUnlinesCopy inh outh
176 , mkBench "words-unwords" href $ do
177 Handles inh outh <- readIORef href
178 BFS.wordsUnwordsCopy inh outh
179 , mkBench "words-unwords-word8" href $ do
180 Handles inh outh <- readIORef href
181 BFS.wordsUnwordsCopyWord8 inh outh
182 , mkBench "words-unwords-arrays" href $ do
183 Handles inh outh <- readIORef href
184 BFA.wordsUnwordsCopy inh outh
185 ]
187 , bgroup "splitting"
188 [ bgroup "predicate"
189 [ mkBench "splitOn \\n (line count)" href $ do
190 Handles inh _ <- readIORef href
191 BFS.splitOn inh
192 , mkBench "splitOnSuffix \\n (line count)" href $ do
193 Handles inh _ <- readIORef href
194 BFS.splitOnSuffix inh
195 , mkBench "wordsBy isSpace (word count)" href $ do
196 Handles inh _ <- readIORef href
197 BFS.wordsBy inh
198 ]
200 , bgroup "empty-pattern"
201 [ mkBench "splitOnSeq \"\"" href $ do
202 Handles inh _ <- readIORef href
203 BFS.splitOnSeq "" inh
204 , mkBench "splitOnSuffixSeq \"\"" href $ do
205 Handles inh _ <- readIORef href
206 BFS.splitOnSuffixSeq "" inh
207 ]
208 , bgroup "short-pattern"
209 [ mkBench "splitOnSeq \\n (line count)" href $ do
210 Handles inh _ <- readIORef href
211 BFS.splitOnSeq "\n" inh
212 , mkBench "splitOnSuffixSeq \\n (line count)" href $ do
213 Handles inh _ <- readIORef href
214 BFS.splitOnSuffixSeq "\n" inh
215 , mkBench "splitOnSeq a" href $ do
216 Handles inh _ <- readIORef href
217 BFS.splitOnSeq "a" inh
218 , mkBench "splitOnSeq \\r\\n" href $ do
219 Handles inh _ <- readIORef href
220 BFS.splitOnSeq "\r\n" inh
221 , mkBench "splitOnSuffixSeq \\r\\n)" href $ do
222 Handles inh _ <- readIORef href
223 BFS.splitOnSuffixSeq "\r\n" inh
224 , mkBench "splitOnSeq aa" href $ do
225 Handles inh _ <- readIORef href
226 BFS.splitOnSeq "aa" inh
227 , mkBench "splitOnSeq aaaa" href $ do
228 Handles inh _ <- readIORef href
229 BFS.splitOnSeq "aaaa" inh
230 , mkBench "splitOnSeq abcdefgh" href $ do
231 Handles inh _ <- readIORef href
232 BFS.splitOnSeq "abcdefgh" inh
233 , mkBench "splitOnSeqUtf8 abcdefgh" href $ do
234 Handles inh _ <- readIORef href
235 BFS.splitOnSeqUtf8 "abcdefgh" inh
236 ]
237 , bgroup "long-pattern"
238 [ mkBench "splitOnSeq abcdefghi" href $ do
239 Handles inh _ <- readIORef href
240 BFS.splitOnSeq "abcdefghi" inh
241 , mkBench "splitOnSeq catcatcatcatcat" href $ do
242 Handles inh _ <- readIORef href
243 BFS.splitOnSeq "catcatcatcatcat" inh
244 , mkBench "splitOnSeq abc...xyz" href $ do
245 Handles inh _ <- readIORef href
246 BFS.splitOnSeq "abcdefghijklmnopqrstuvwxyz" inh
247 , mkBench "splitOnSuffixSeq abc...xyz" href $ do
248 Handles inh _ <- readIORef href
249 BFS.splitOnSuffixSeq "abcdefghijklmnopqrstuvwxyz" inh
250 , mkBench "splitOnSeqUtf8 abc...xyz" href $ do
251 Handles inh _ <- readIORef href
252 BFS.splitOnSeqUtf8 "abcdefghijklmnopqrstuvwxyz" inh
253 ]
254 ]
255#endif
256 ]
258 where
260 mkBench :: NFData b => String -> IORef Handles -> IO b -> Benchmark
261 mkBench name ref action =
262 bench name $ perRunEnv (do
263 (Handles inh outh) <- readIORef ref
264 hClose inh
265 hClose outh
266 inHandle <- openFile infile ReadMode
267 outHandle <- openFile outfile WriteMode
268 writeIORef ref (Handles inHandle outHandle)
269 )
270 (\_ -> action)