File: bench.hs

package info (click to toggle)
haskell-scanner 0.3.1-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 164 kB
  • sloc: haskell: 810; makefile: 3
file content (174 lines) | stat: -rw-r--r-- 6,000 bytes parent folder | download | duplicates (4)
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
{-# LANGUAGE OverloadedStrings #-}

module Main
( main
)
where

import qualified Scanner

import qualified Redis.Reply as Redis
import qualified Redis.Atto
import qualified Redis.Zepto
import qualified Redis.Scanner

import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import qualified Data.Attoparsec.ByteString as Atto
import qualified Data.Attoparsec.Zepto as Zepto
import qualified Data.Serialize.Get as Cereal

import Criterion
import Criterion.Main

main :: IO ()
main = do
  let smallStringInput = "+OK\r\n"
      longStringInput = "+11111111111111111111111111122222222222222222222233333333333333333333333444444444444444444445555555555555555555555666666666666666666677777777777777777777888888888888888888888999999999999999999000000000000000000\r\n"
      intInput = ":123\r\n"
      bulkInput = "$10\r\n0123456789\r\n"
      multiInput = "*3\r\n+A\r\n+B\r\n+C\r\n"
      binaryInput = ByteString.pack [5, 65, 66, 67, 68, 69]
  print (stringAtto smallStringInput)
  print (stringScanner smallStringInput)
  print (stringWordScanner smallStringInput)
  print (redisByteStringReply smallStringInput)
  print (redisAttoReply smallStringInput)
  print (redisZeptoReply smallStringInput)
  print (redisScannerReply smallStringInput)
  print (redisAttoReply intInput)
  print (redisZeptoReply intInput)
  print (redisScannerReply intInput)
  print (redisAttoReply bulkInput)
  print (redisZeptoReply bulkInput)
  print (redisScannerReply bulkInput)
  print (redisAttoReply multiInput)
  print (redisZeptoReply multiInput)
  print (redisScannerReply multiInput)
  defaultMain
    [ bgroup "scanner"
      [ bgroup "string"
        [ bench "Atto" $ whnf stringAtto smallStringInput
        , bench "Scanner" $ whnf stringScanner smallStringInput
        , bench "WordScanner" $ whnf stringWordScanner smallStringInput
        ]
      ]

    , bgroup "redis"
      [ bgroup "small string"
        [ bench "Atto" $ whnf redisAttoReply smallStringInput
        , bench "Zepto" $ whnf redisZeptoReply smallStringInput
        , bench "Scanner" $ whnf redisScannerReply smallStringInput
        , bench "ByteString" $ whnf redisByteStringReply smallStringInput
        ]
      , bgroup "long string"
        [ bench "Atto" $ whnf redisAttoReply longStringInput
        , bench "Zepto" $ whnf redisZeptoReply longStringInput
        , bench "Scanner" $ whnf redisScannerReply longStringInput
        , bench "ByteString" $ whnf redisByteStringReply longStringInput
        ]

      , bgroup "integer"
        [ bench "Atto" $ whnf redisAttoReply intInput
        , bench "Zepto" $ whnf redisZeptoReply intInput
        , bench "Scanner" $ whnf redisScannerReply intInput
        ]

      , bgroup "bulk"
        [ bench "Atto" $ whnf redisAttoReply bulkInput
        , bench "Zepto" $ whnf redisZeptoReply bulkInput
        , bench "Scanner" $ whnf redisScannerReply bulkInput
        ]

      , bgroup "multi"
        [ bench "Atto" $ whnf redisAttoReply multiInput
        , bench "Zepto" $ whnf redisZeptoReply multiInput
        , bench "Scanner" $ whnf redisScannerReply multiInput
        ]
      ]

    , bgroup "cereal"
      [ bench "Cereal" $ whnf binaryCereal binaryInput
      , bench "Scanner" $ whnf binaryScanner binaryInput
      ]
    ]

{-# NOINLINE stringAtto #-}
stringAtto :: ByteString -> Either String ()
stringAtto bs = case Atto.parse (Atto.string "+OK\r\n") bs of
  Atto.Done _ _ -> Right ()
  Atto.Fail _ _ err -> Left err
  Atto.Partial _ -> Left "Not enough input"

{-# NOINLINE stringScanner #-}
stringScanner :: ByteString -> Either String ()
stringScanner bs = case Scanner.scan (Scanner.string "+OK\r\n") bs of
  Scanner.Done _ _ -> Right ()
  Scanner.Fail _ err -> Left err
  Scanner.More _ -> Left "Not enought input"

{-# NOINLINE stringWordScanner #-}
stringWordScanner :: ByteString -> Either String ()
stringWordScanner bs = case Scanner.scan s bs of
  Scanner.Done _ _ -> Right ()
  Scanner.Fail _ err -> Left err
  Scanner.More _ -> Left "Not enought input"
  where
  s = do
    Scanner.char8 '+'
    Scanner.char8 'O'
    Scanner.char8 'K'
    Scanner.char8 '\r'
    Scanner.char8 '\n'

{-# NOINLINE redisAttoReply #-}
redisAttoReply :: ByteString -> Either String Redis.Reply
redisAttoReply bs = case Atto.parse Redis.Atto.reply bs of
  Atto.Done _ r -> Right r
  Atto.Fail _ _ err -> Left err
  Atto.Partial _ -> Left "Not enough input"

{-# NOINLINE redisZeptoReply #-}
redisZeptoReply :: ByteString -> Either String Redis.Reply
redisZeptoReply = Zepto.parse Redis.Zepto.reply

{-# NOINLINE redisScannerReply #-}
redisScannerReply :: ByteString -> Either String Redis.Reply
redisScannerReply bs = case Scanner.scan Redis.Scanner.reply bs of
  Scanner.Done _ r -> Right r
  Scanner.Fail _ err -> Left err
  Scanner.More _ -> Left "Not enought input"

{-# NOINLINE redisByteStringReply #-}
redisByteStringReply :: ByteString -> Either String Redis.Reply
redisByteStringReply bs = case ByteString.uncons bs of
  Just (c, bs') -> case c of
    43 -> let (l, r) = ByteString.span (/= 13) bs'
          in case ByteString.uncons r of
            Just (c', bs'') -> case c' of
              13 -> case ByteString.uncons bs'' of
                Just (c'', _) -> case c'' of
                  10 -> Right (Redis.String l)
                  _ -> Left "Unexpected input"
                Nothing -> Left "Not enough input"
              _ -> Left "Unexpected input"
            Nothing -> Left "Not enought input"
    _ -> Left "Unknown type"
  Nothing -> Left "Not enought input"

binaryScanner :: ByteString -> Either String ByteString
binaryScanner bs = case Scanner.scan p bs of
  Scanner.Done _ r -> Right r
  Scanner.Fail _ err -> Left err
  Scanner.More _ -> Left "Not enought input"
  where
  p = do
    n <- fromIntegral <$> Scanner.anyWord8
    Scanner.take n

binaryCereal :: ByteString -> Either String ByteString
binaryCereal bs = Cereal.runGet g bs
  where
  g = do
    n <- fromIntegral <$> Cereal.getWord8
    Cereal.getBytes n