aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Benchmarks/ServerChunkSize.hs
blob: 7b01c6817c78466316ccedae762cdd3b892bb84c (plain) (blame)
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
-- | A benchmark for measuring the impact of lazy bytestring chunk size on
-- server performance.
--
{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Concurrent (forkIO)
import Control.Monad (forever)
import Data.Monoid (mappend)
import Network (listenOn, PortID (PortNumber))
import Network.Socket (accept, sClose)
import Prelude hiding (putStrLn)
import System.Environment (getArgs)

import Network.Socket.ByteString (recv, send)
import Network.Socket.ByteString.Lazy (sendAll)
import qualified Data.ByteString.Char8 as SBC
import qualified Data.ByteString.Lazy as LB

-- | Generate a 128k response, with a given chunk size.
--
makeResponse :: Int            -- ^ Chunk size.
             -> LB.ByteString  -- ^ Result.
makeResponse chunkSize =
    let chunks = createChunks chunkSize totalSize
    in LB.fromChunks chunks
  where
    -- A 64 kilobyte response.
    totalSize = 128 * 1024

    createChunks c s
      | c < s     = SBC.replicate c 'a' : createChunks c (s - c)
      | otherwise = SBC.replicate s 'a' : []

main :: IO ()
main = do
    args <- getArgs
    let port = PortNumber $ fromIntegral $ (read $ head args :: Int)
        chunkSize = read $ args !! 1

    socket <- listenOn port
    forever $ do
        (s, _) <- accept socket
        forkIO (respond chunkSize s)
  where
    respond chunkSize s = do
        _ <- recv s 1024
        _ <- send s $ "HTTP/1.1 200 OK\r\n"
            `mappend` "Content-Type: text/html; charset=UTF-8\r\n"
            `mappend` "\r\n"
        sendAll s $ makeResponse chunkSize
        sClose s