-
Notifications
You must be signed in to change notification settings - Fork 157
/
FoldLines.hs
58 lines (54 loc) · 1.49 KB
/
FoldLines.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
-- | Read a file line-by-line using handles, and perform a fold over the lines.
-- The fold is used here to calculate the number of lines in the file.
--
-- Tested in this benchmark:
--
-- * Buffered, line-based IO
--
{-# LANGUAGE BangPatterns #-}
module Benchmarks.FoldLines
( benchmark
) where
import Criterion (Benchmark, bgroup, bench)
import System.IO
import qualified Data.ByteString as B
import qualified Data.Text as T
import qualified Data.Text.IO as T
benchmark :: FilePath -> IO Benchmark
benchmark fp = return $ bgroup "ReadLines"
[ bench "Text" $ withHandle $ foldLinesT (\n _ -> n + 1) (0 :: Int)
, bench "ByteString" $ withHandle $ foldLinesB (\n _ -> n + 1) (0 :: Int)
]
where
withHandle f = do
h <- openFile fp ReadMode
hSetBuffering h (BlockBuffering (Just 16384))
x <- f h
hClose h
return x
-- | Text line fold
--
foldLinesT :: (a -> T.Text -> a) -> a -> Handle -> IO a
foldLinesT f z0 h = go z0
where
go !z = do
eof <- hIsEOF h
if eof
then return z
else do
l <- T.hGetLine h
let z' = f z l in go z'
{-# INLINE foldLinesT #-}
-- | ByteString line fold
--
foldLinesB :: (a -> B.ByteString -> a) -> a -> Handle -> IO a
foldLinesB f z0 h = go z0
where
go !z = do
eof <- hIsEOF h
if eof
then return z
else do
l <- B.hGetLine h
let z' = f z l in go z'
{-# INLINE foldLinesB #-}