]>
Commit | Line | Data |
---|---|---|
675085c2 JG |
1 | -- | A benchmark for measuring the impact of lazy bytestring chunk size on |
2 | -- server performance. | |
3 | -- | |
4 | {-# LANGUAGE OverloadedStrings #-} | |
5 | module Main where | |
6 | ||
7 | import Control.Concurrent (forkIO) | |
8 | import Control.Monad (forever) | |
9 | import Data.Monoid (mappend) | |
10 | import Network (listenOn, PortID (PortNumber)) | |
11 | import Network.Socket (accept, sClose) | |
12 | import Prelude hiding (putStrLn) | |
13 | import System.Environment (getArgs) | |
14 | ||
15 | import Network.Socket.ByteString (recv, send) | |
16 | import Network.Socket.ByteString.Lazy (sendAll) | |
17 | import qualified Data.ByteString.Char8 as SBC | |
18 | import qualified Data.ByteString.Lazy as LB | |
19 | ||
20 | -- | Generate a 128k response, with a given chunk size. | |
21 | -- | |
22 | makeResponse :: Int -- ^ Chunk size. | |
23 | -> LB.ByteString -- ^ Result. | |
24 | makeResponse chunkSize = | |
25 | let chunks = createChunks chunkSize totalSize | |
26 | in LB.fromChunks chunks | |
27 | where | |
28 | -- A 64 kilobyte response. | |
29 | totalSize = 128 * 1024 | |
30 | ||
31 | createChunks c s | |
32 | | c < s = SBC.replicate c 'a' : createChunks c (s - c) | |
33 | | otherwise = SBC.replicate s 'a' : [] | |
34 | ||
35 | main :: IO () | |
36 | main = do | |
37 | args <- getArgs | |
38 | let port = PortNumber $ fromIntegral $ (read $ head args :: Int) | |
39 | chunkSize = read $ args !! 1 | |
40 | ||
41 | socket <- listenOn port | |
42 | forever $ do | |
43 | (s, _) <- accept socket | |
44 | forkIO (respond chunkSize s) | |
45 | where | |
46 | respond chunkSize s = do | |
47 | _ <- recv s 1024 | |
48 | _ <- send s $ "HTTP/1.1 200 OK\r\n" | |
49 | `mappend` "Content-Type: text/html; charset=UTF-8\r\n" | |
50 | `mappend` "\r\n" | |
51 | sendAll s $ makeResponse chunkSize | |
52 | sClose s |