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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE DeriveGeneric #-}
module Main (main) where
import Control.DeepSeq
import Data.Maybe
import Data.Attoparsec.ByteString as Atto
import Data.ByteString as B
import Data.ByteString.Lazy as BL
import Data.List as L
import Criterion.Main
import System.Environment
import GHC.Generics
import "bencode" Data.BEncode as A
import Data.AttoBencode as B
import Data.AttoBencode.Parser as B
import "bencoding" Data.BEncode as C
instance NFData A.BEncode where
rnf (A.BInt i) = rnf i
rnf (A.BString s) = rnf s
rnf (A.BList l) = rnf l
rnf (A.BDict m) = rnf m
instance NFData B.BValue where
rnf (B.BInt i) = rnf i
rnf (B.BString s) = rnf s
rnf (B.BList l) = rnf l
rnf (B.BDict d) = rnf d
getRight :: Either String a -> a
getRight = either error id
data List a = Cons a (List a) | Nil
deriving Generic
instance BEncodable a => BEncodable (List a)
instance NFData a => NFData (List a) where
rnf Nil = ()
rnf (Cons x xs) = rnf (x, xs)
replicate' :: Int -> a -> List a
replicate' c x
| c >= 0 = go c
| otherwise = Nil
where
go 0 = Nil
go n = Cons x $ go (pred n)
main :: IO ()
main = do
(path : args) <- getArgs
torrentFile <- B.readFile path
let lazyTorrentFile = fromChunks [torrentFile]
case rnf (torrentFile, lazyTorrentFile) of
() -> return ()
withArgs args $
defaultMain
[ bench "decode/bencode" $
nf A.bRead lazyTorrentFile
, bench "decode/AttoBencode" $
nf (getRight . Atto.parseOnly bValue) torrentFile
, bench "decode/bencoding" $
nf (getRight . C.decode) torrentFile
, let Just v = A.bRead lazyTorrentFile in
bench "encode/bencode" $ nf A.bPack v
, let Right v = Atto.parseOnly bValue torrentFile in
bench "encode/AttoBencode" $ nf B.encode v
, let Right v = C.decode torrentFile in
bench "encode/bencoding" $ nf C.encode v
, bench "decode+encode/bencode" $
nf (A.bPack . fromJust . A.bRead) lazyTorrentFile
, bench "decode+encode/AttoBencode" $
nf (B.encode . getRight . Atto.parseOnly bValue) torrentFile
, bench "decode+encode/bencoding" $
nf (C.encode . getRight . C.decode) torrentFile
, bench "list10000int/bencode/encode" $
nf (A.bPack . A.BList . L.map (A.BInt . fromIntegral))
[0..10000 :: Int]
, bench "list10000int/attobencode/encode" $
nf B.encode [1..20000 :: Int]
, bench "list10000int/bencoding/encode" $
nf C.encoded [1..20000 :: Int]
, let d = A.bPack $ A.BList $
L.map A.BInt (L.replicate 1000 (0 :: Integer))
in d `seq` (bench "list1000int/bencode/decode" $ nf
(fromJust . A.bRead :: BL.ByteString -> A.BEncode) d)
, let d = BL.toStrict (C.encoded (L.replicate 10000 ()))
in d `seq` (bench "list10000unit/bencoding/decode" $ nf
(C.decoded :: B.ByteString -> Either String [()]) d)
, let d = BL.toStrict $ C.encoded $ L.replicate 10000 (0 :: Int)
in d `seq` (bench "list10000int/bencoding/decode" $ nf
(C.decoded :: B.ByteString -> Either String [Int]) d)
, let d = L.replicate 10000 0
in bench "list10000int/bencoding/encode>>decode" $
nf (getRight . C.decoded . BL.toStrict . C.encoded
:: [Int] -> [Int] )
d
, let d = replicate' 10000 0
in bench "list10000int/bencoding/encode>>decode/generic" $
nf (getRight . C.decoded . BL.toStrict . C.encoded
:: List Int -> List Int)
d
]
|