git.iko.soy/distributed-process
on master help sign in
Resurrect ping benchmarks
commitae6097eaa152d065413298e5ddc9d454a17153ba authorEdsko de Vries <edsko@edsko.net> dateWed 8 Aug 2012, 10:54 (14 years ago) parent43721ca
14 files changed+1251
network-transport-tcp/benchmarks/Headers.gnuplot+16 network-transport-tcp/benchmarks/Indirection.gnuplot+16 network-transport-tcp/benchmarks/JustPingC.c+150 network-transport-tcp/benchmarks/JustPingCacheHeader.hs+134 network-transport-tcp/benchmarks/JustPingHaskell.hs+105 network-transport-tcp/benchmarks/JustPingOneRecv.hs+131 network-transport-tcp/benchmarks/JustPingThroughChan.hs+127 network-transport-tcp/benchmarks/JustPingThroughMVar.hs+127 network-transport-tcp/benchmarks/JustPingTransport.hs+95 network-transport-tcp/benchmarks/JustPingTwoSocketPairs.hs+151 network-transport-tcp/benchmarks/JustPingWithHeader.hs+131 network-transport-tcp/benchmarks/Makefile+55 network-transport-tcp/benchmarks/NewTransport.gnuplot+8 network-transport-tcp/benchmarks/cabal_macros.h+5
network-transport-tcp/benchmarks/Headers.gnuplotnew file+16
@@ -0,0 +1,16 @@
1+set title "Roundtrip (us)"
2+set yrange [0:150]
3+plot "JustPingHaskellNT.data" smooth bezier with lines title "JustPingHaskell (NOT -threaded)", \
4+ "JustPingHaskell.data" smooth bezier with lines title "JustPingHaskell", \
5+ "JustPingWithHeader.data" smooth bezier with lines title "JustPingWithHeader", \
6+ "JustPingOneRecv.data" smooth bezier with lines title "JustPingOneRecv", \
7+ "JustPingCacheHeader.data" smooth bezier with lines title "JustPingCacheHeader", \
8+ "JustPingC.data" smooth bezier with lines title "JustPingC"
9+set terminal postscript color
10+set output "Headers.ps"
11+plot "JustPingHaskellNT.data" smooth bezier with lines title "JustPingHaskell (NOT -threaded)", \
12+ "JustPingHaskell.data" smooth bezier with lines title "JustPingHaskell", \
13+ "JustPingWithHeader.data" smooth bezier with lines title "JustPingWithHeader", \
14+ "JustPingOneRecv.data" smooth bezier with lines title "JustPingOneRecv", \
15+ "JustPingCacheHeader.data" smooth bezier with lines title "JustPingCacheHeader", \
16+ "JustPingC.data" smooth bezier with lines title "JustPingC"
network-transport-tcp/benchmarks/Indirection.gnuplotnew file+16
@@ -0,0 +1,16 @@
1+set title "Roundtrip (us)"
2+set yrange [0:150]
3+plot "JustPingWithHeader.data" smooth bezier with lines title "JustPingWithHeader", \
4+ "JustPingThroughChan.data" smooth bezier with lines title "JustPingThroughChan", \
5+ "JustPingThroughMVar.data" smooth bezier with lines title "JustPingThroughMVar", \
6+ "JustPingTwoSocketPairs.data" smooth bezier with lines title "JustPingTwoSocketPairs", \
7+ "JustPingTwoSocketPairsND.data" smooth bezier with lines title "JustPingTwoSocketPairs (--NoDelay)", \
8+ "JustPingTransport.data" smooth bezier with lines title "JustPingTransport"
9+set terminal postscript color
10+set output "Indirection.ps"
11+plot "JustPingWithHeader.data" smooth bezier with lines title "JustPingWithHeader", \
12+ "JustPingThroughChan.data" smooth bezier with lines title "JustPingThroughChan", \
13+ "JustPingThroughMVar.data" smooth bezier with lines title "JustPingThroughMVar", \
14+ "JustPingTwoSocketPairs.data" smooth bezier with lines title "JustPingTwoSocketPairs", \
15+ "JustPingTwoSocketPairsND.data" smooth bezier with lines title "JustPingTwoSocketPairs (--NoDelay)", \
16+ "JustPingTransport.data" smooth bezier with lines title "JustPingTransport"
network-transport-tcp/benchmarks/JustPingC.cnew file+150
@@ -0,0 +1,150 @@
1+#include <stdio.h>
2+#include <stdlib.h>
3+#include <sys/types.h>
4+#include <sys/socket.h>
5+#include <netdb.h>
6+#include <string.h>
7+#include <unistd.h>
8+#include <signal.h>
9+#include <errno.h>
10+#include <time.h>
11+#include <sys/time.h>
12+#include <math.h>
13+
14+// Note: this is not consistent across CPUs (and hence across threads on multicore machines)
15+double timestamp() {
16+ struct timeval tp;
17+ gettimeofday(&tp, NULL);
18+ return ((double) tp.tv_sec) * 1e6 + (double) tp.tv_usec;
19+}
20+
21+int server() {
22+ printf("starting server\n");
23+
24+ struct addrinfo hints, *res;
25+ int error, server_socket;
26+
27+ memset(&hints, 0, sizeof(hints));
28+ hints.ai_family = PF_INET;
29+ hints.ai_socktype = SOCK_STREAM;
30+ hints.ai_flags = AI_PASSIVE;
31+
32+ error = getaddrinfo(NULL, "8080", &hints, &res);
33+ if(error) {
34+ printf("server error: %s\n", gai_strerror(error));
35+ return -1;
36+ }
37+
38+ server_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
39+ if(server_socket < 0) {
40+ printf("server error: could not create socket\n");
41+ return -1;
42+ }
43+
44+ int yes = 1;
45+ if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
46+ printf("server error: could not set socket options\n");
47+ return -1;
48+ }
49+
50+ if(bind(server_socket, res->ai_addr, res->ai_addrlen) < 0) {
51+ printf("server error: could not bind to socket\n");
52+ return -1;
53+ }
54+
55+ listen(server_socket, 5);
56+
57+ int client_socket;
58+ struct sockaddr_storage client_addr;
59+ socklen_t addr_size;
60+ client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_size);
61+
62+ for(;;) {
63+ char* buf = malloc(8);
64+ ssize_t read = recv(client_socket, buf, 8, 0);
65+ if(read == 0) {
66+ free(buf);
67+ break;
68+ }
69+ // printf("server received '%s'\n", buf);
70+ send(client_socket, buf, 8, 0);
71+ free(buf);
72+ }
73+
74+ freeaddrinfo(res);
75+ return 0;
76+}
77+
78+int client(int pings) {
79+ printf("starting client\n");
80+
81+ struct addrinfo hints, *res;
82+ int error, client_socket;
83+
84+ memset(&hints, 0, sizeof(hints));
85+ hints.ai_family = PF_INET;
86+ hints.ai_socktype = SOCK_STREAM;
87+
88+ error = getaddrinfo("127.0.0.1", "8080", &hints, &res);
89+ if(error) {
90+ printf("client error: %s\n", gai_strerror(error));
91+ return -1;
92+ }
93+
94+ client_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
95+ if(client_socket < 0) {
96+ printf("client error: could not create socket\n");
97+ return -1;
98+ }
99+
100+ if(connect(client_socket, res->ai_addr, res->ai_addrlen) < 0) {
101+ printf("client error: could not connect: %s\n", strerror(errno));
102+ return -1;
103+ }
104+
105+ for(int i = 0; i < pings; i++) {
106+ double timestamp_before = timestamp();
107+
108+ send(client_socket, "ping123", 8, 0);
109+
110+ char *buf = malloc(8);
111+ ssize_t read = recv(client_socket, buf, 8, 0);
112+
113+ if(read == 0) {
114+ printf("server exited prematurely\n");
115+ free(buf);
116+ break;
117+ }
118+
119+ // printf("client received '%s'\n", buf);
120+ free(buf);
121+
122+ double timestamp_after = timestamp();
123+ fprintf(stderr, "%i %lf\n", i, timestamp_after - timestamp_before);
124+ }
125+
126+ printf("client did %d pings\n", pings);
127+
128+ freeaddrinfo(res);
129+ return 0;
130+}
131+
132+int usage(int argc, char** argv) {
133+ printf("usage: %s <number of pings>\n", argv[0]);
134+ return -1;
135+}
136+
137+int main(int argc, char** argv) {
138+ if(argc != 2) {
139+ return usage(argc, argv);
140+ }
141+
142+ if(fork() == 0) {
143+ // TODO: we should wait until we know the server is ready
144+ int pings = 0;
145+ sscanf(argv[1], "%d", &pings);
146+ return client(pings);
147+ } else {
148+ return server();
149+ }
150+}
network-transport-tcp/benchmarks/JustPingCacheHeader.hsnew file+134
@@ -0,0 +1,134 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+
31+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
33+
34+main :: IO ()
35+main = do
36+ [pingsStr] <- getArgs
37+ serverReady <- newEmptyMVar
38+ clientDone <- newEmptyMVar
39+
40+ -- Start the server
41+ forkIO $ do
42+ putStrLn "server: creating TCP connection"
43+ serverAddrs <- getAddrInfo
44+ (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
45+ Nothing
46+ (Just "8080")
47+ let serverAddr = head serverAddrs
48+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
49+ setSocketOption sock ReuseAddr 1
50+ bindSocket sock (addrAddress serverAddr)
51+
52+ putStrLn "server: awaiting client connection"
53+ putMVar serverReady ()
54+ listen sock 1
55+ (clientSock, clientAddr) <- accept sock
56+
57+ putStrLn "server: listening for pings"
58+ pong clientSock
59+
60+ -- Start the client
61+ forkIO $ do
62+ takeMVar serverReady
63+ let pings = read pingsStr
64+ serverAddrs <- getAddrInfo
65+ Nothing
66+ (Just "127.0.0.1")
67+ (Just "8080")
68+ let serverAddr = head serverAddrs
69+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
70+
71+ N.connect sock (addrAddress serverAddr)
72+
73+ ping sock pings
74+ putMVar clientDone ()
75+
76+ -- Wait for the client to finish
77+ takeMVar clientDone
78+
79+pingMessage :: ByteString
80+pingMessage = pack "ping123"
81+
82+ping :: Socket -> Int -> IO ()
83+ping sock pings = go pings
84+ where
85+ go :: Int -> IO ()
86+ go 0 = do
87+ putStrLn $ "client did " ++ show pings ++ " pings"
88+ go !i = do
89+ before <- getCurrentTime
90+ send sock pingMessage
91+ bs <- recv sock 8
92+ after <- getCurrentTime
93+ -- putStrLn $ "client received " ++ unpack bs
94+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
95+ hPutStrLn stderr $ show i ++ " " ++ show latency
96+ go (i - 1)
97+
98+pong :: Socket -> IO ()
99+pong sock = do
100+ bs <- recv sock 8
101+ -- putStrLn $ "server received " ++ unpack bs
102+ when (BS.length bs > 0) $ do
103+ send sock bs
104+ pong sock
105+
106+-- | Wrapper around NBS.recv (for profiling)
107+recv :: Socket -> Int -> IO ByteString
108+recv sock i = do
109+ (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
110+ -- Ignore header
111+ return payload
112+
113+-- | Cached header
114+header :: ByteString
115+header = pack "fake"
116+
117+-- | Wrapper around NBS.send (for profiling)
118+send :: Socket -> ByteString -> IO ()
119+send sock bs = do
120+ NBS.sendMany sock [header, bs]
121+
122+-- | Encode length (manual for now)
123+encodeLength :: Int32 -> IO ByteString
124+encodeLength i32 =
125+ BSI.create 4 $ \p ->
126+ pokeByteOff p 0 (htonl (fromIntegral i32))
127+
128+-- | Decode length (manual for now)
129+decodeLength :: ByteString -> IO Int32
130+decodeLength bs =
131+ let (fp, _, _) = BSI.toForeignPtr bs in
132+ withForeignPtr fp $ \p -> do
133+ w32 <- peekByteOff p 0
134+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/JustPingHaskell.hsnew file+105
@@ -0,0 +1,105 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+
27+main :: IO ()
28+main = do
29+ [pingsStr] <- getArgs
30+ serverReady <- newEmptyMVar
31+ clientDone <- newEmptyMVar
32+
33+ -- Start the server
34+ forkIO $ do
35+ putStrLn "server: creating TCP connection"
36+ serverAddrs <- getAddrInfo
37+ (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
38+ Nothing
39+ (Just "8080")
40+ let serverAddr = head serverAddrs
41+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
42+ setSocketOption sock ReuseAddr 1
43+ bindSocket sock (addrAddress serverAddr)
44+
45+ putStrLn "server: awaiting client connection"
46+ putMVar serverReady ()
47+ listen sock 1
48+ (clientSock, clientAddr) <- accept sock
49+
50+ putStrLn "server: listening for pings"
51+ pong clientSock
52+
53+ -- Start the client
54+ forkIO $ do
55+ takeMVar serverReady
56+ let pings = read pingsStr
57+ serverAddrs <- getAddrInfo
58+ Nothing
59+ (Just "127.0.0.1")
60+ (Just "8080")
61+ let serverAddr = head serverAddrs
62+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
63+
64+ N.connect sock (addrAddress serverAddr)
65+
66+ ping sock pings
67+ putMVar clientDone ()
68+
69+ -- Wait for the client to finish
70+ takeMVar clientDone
71+
72+pingMessage :: ByteString
73+pingMessage = pack "ping123"
74+
75+ping :: Socket -> Int -> IO ()
76+ping sock pings = go pings
77+ where
78+ go :: Int -> IO ()
79+ go 0 = do
80+ putStrLn $ "client did " ++ show pings ++ " pings"
81+ go !i = do
82+ before <- getCurrentTime
83+ send sock pingMessage
84+ bs <- recv sock 8
85+ after <- getCurrentTime
86+ -- putStrLn $ "client received " ++ unpack bs
87+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
88+ hPutStrLn stderr $ show i ++ " " ++ show latency
89+ go (i - 1)
90+
91+pong :: Socket -> IO ()
92+pong sock = do
93+ bs <- recv sock 8
94+ -- putStrLn $ "server received " ++ unpack bs
95+ when (BS.length bs > 0) $ do
96+ send sock bs
97+ pong sock
98+
99+-- | Wrapper around NBS.recv (for profiling)
100+recv :: Socket -> Int -> IO ByteString
101+recv = NBS.recv
102+
103+-- | Wrapper around NBS.send (for profiling)
104+send :: Socket -> ByteString -> IO Int
105+send = NBS.send
network-transport-tcp/benchmarks/JustPingOneRecv.hsnew file+131
@@ -0,0 +1,131 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+
31+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
33+
34+main :: IO ()
35+main = do
36+ [pingsStr] <- getArgs
37+ serverReady <- newEmptyMVar
38+ clientDone <- newEmptyMVar
39+
40+ -- Start the server
41+ forkIO $ do
42+ putStrLn "server: creating TCP connection"
43+ serverAddrs <- getAddrInfo
44+ (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
45+ Nothing
46+ (Just "8080")
47+ let serverAddr = head serverAddrs
48+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
49+ setSocketOption sock ReuseAddr 1
50+ bindSocket sock (addrAddress serverAddr)
51+
52+ putStrLn "server: awaiting client connection"
53+ putMVar serverReady ()
54+ listen sock 1
55+ (clientSock, clientAddr) <- accept sock
56+
57+ putStrLn "server: listening for pings"
58+ pong clientSock
59+
60+ -- Start the client
61+ forkIO $ do
62+ takeMVar serverReady
63+ let pings = read pingsStr
64+ serverAddrs <- getAddrInfo
65+ Nothing
66+ (Just "127.0.0.1")
67+ (Just "8080")
68+ let serverAddr = head serverAddrs
69+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
70+
71+ N.connect sock (addrAddress serverAddr)
72+
73+ ping sock pings
74+ putMVar clientDone ()
75+
76+ -- Wait for the client to finish
77+ takeMVar clientDone
78+
79+pingMessage :: ByteString
80+pingMessage = pack "ping123"
81+
82+ping :: Socket -> Int -> IO ()
83+ping sock pings = go pings
84+ where
85+ go :: Int -> IO ()
86+ go 0 = do
87+ putStrLn $ "client did " ++ show pings ++ " pings"
88+ go !i = do
89+ before <- getCurrentTime
90+ send sock pingMessage
91+ bs <- recv sock 8
92+ after <- getCurrentTime
93+ -- putStrLn $ "client received " ++ unpack bs
94+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
95+ hPutStrLn stderr $ show i ++ " " ++ show latency
96+ go (i - 1)
97+
98+pong :: Socket -> IO ()
99+pong sock = do
100+ bs <- recv sock 8
101+ -- putStrLn $ "server received " ++ unpack bs
102+ when (BS.length bs > 0) $ do
103+ send sock bs
104+ pong sock
105+
106+-- | Wrapper around NBS.recv (for profiling)
107+recv :: Socket -> Int -> IO ByteString
108+recv sock i = do
109+ (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
110+ length <- decodeLength header -- Ignored
111+ return payload
112+
113+-- | Wrapper around NBS.send (for profiling)
114+send :: Socket -> ByteString -> IO ()
115+send sock bs = do
116+ length <- encodeLength (fromIntegral (BS.length bs))
117+ NBS.sendMany sock [length, bs]
118+
119+-- | Encode length (manual for now)
120+encodeLength :: Int32 -> IO ByteString
121+encodeLength i32 =
122+ BSI.create 4 $ \p ->
123+ pokeByteOff p 0 (htonl (fromIntegral i32))
124+
125+-- | Decode length (manual for now)
126+decodeLength :: ByteString -> IO Int32
127+decodeLength bs =
128+ let (fp, _, _) = BSI.toForeignPtr bs in
129+ withForeignPtr fp $ \p -> do
130+ w32 <- peekByteOff p 0
131+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/JustPingThroughChan.hsnew file+127
@@ -0,0 +1,127 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfo, AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
31+
32+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
33+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
34+
35+passive :: Maybe AddrInfo
36+passive = Just (defaultHints { addrFlags = [AI_PASSIVE] })
37+
38+main = do
39+ [pingsStr] <- getArgs
40+ serverReady <- newEmptyMVar
41+ clientDone <- newEmptyMVar
42+
43+ -- Start the server
44+ forkIO $ do
45+ -- Initialize the server
46+ serverAddr:_ <- getAddrInfo passive Nothing (Just "8080")
47+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
48+ setSocketOption sock ReuseAddr 1
49+ bindSocket sock (addrAddress serverAddr)
50+ listen sock 1
51+
52+ -- Set up multiplexing channel
53+ multiplexChannel <- newChan
54+
55+ -- Wait for incoming connections (pings from the client)
56+ putMVar serverReady ()
57+ (clientSock, pingAddr) <- accept sock
58+ forkIO $ socketToChan clientSock multiplexChannel
59+
60+ -- Reply to the client
61+ forever $ readChan multiplexChannel >>= send clientSock
62+
63+ -- Start the client
64+ forkIO $ do
65+ takeMVar serverReady
66+ serverAddr:_ <- getAddrInfo Nothing (Just "127.0.0.1") (Just "8080")
67+ clientSock <- socket (addrFamily serverAddr) Stream defaultProtocol
68+ N.connect clientSock (addrAddress serverAddr)
69+ ping clientSock (read pingsStr)
70+ putMVar clientDone ()
71+
72+ -- Wait for the client to finish
73+ takeMVar clientDone
74+
75+socketToChan :: Socket -> Chan ByteString -> IO ()
76+socketToChan sock chan = go
77+ where
78+ go = do bs <- recv sock
79+ when (BS.length bs > 0) $ do
80+ writeChan chan bs
81+ go
82+
83+pingMessage :: ByteString
84+pingMessage = pack "ping123"
85+
86+ping :: Socket -> Int -> IO ()
87+ping sock pings = go pings
88+ where
89+ go :: Int -> IO ()
90+ go 0 = do
91+ putStrLn $ "client did " ++ show pings ++ " pings"
92+ go !i = do
93+ before <- getCurrentTime
94+ send sock pingMessage
95+ bs <- recv sock
96+ after <- getCurrentTime
97+ -- putStrLn $ "client received " ++ unpack bs
98+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
99+ hPutStrLn stderr $ show i ++ " " ++ show latency
100+ go (i - 1)
101+
102+-- | Receive a package
103+recv :: Socket -> IO ByteString
104+recv sock = do
105+ header <- NBS.recv sock 4
106+ length <- decodeLength header
107+ NBS.recv sock (fromIntegral (length :: Int32))
108+
109+-- | Send a package
110+send :: Socket -> ByteString -> IO ()
111+send sock bs = do
112+ length <- encodeLength (fromIntegral (BS.length bs))
113+ NBS.sendMany sock [length, bs]
114+
115+-- | Encode length (manual for now)
116+encodeLength :: Int32 -> IO ByteString
117+encodeLength i32 =
118+ BSI.create 4 $ \p ->
119+ pokeByteOff p 0 (htonl (fromIntegral i32))
120+
121+-- | Decode length (manual for now)
122+decodeLength :: ByteString -> IO Int32
123+decodeLength bs =
124+ let (fp, _, _) = BSI.toForeignPtr bs in
125+ withForeignPtr fp $ \p -> do
126+ w32 <- peekByteOff p 0
127+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/JustPingThroughMVar.hsnew file+127
@@ -0,0 +1,127 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfo, AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (MVar, newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
31+
32+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
33+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
34+
35+passive :: Maybe AddrInfo
36+passive = Just (defaultHints { addrFlags = [AI_PASSIVE] })
37+
38+main = do
39+ [pingsStr] <- getArgs
40+ serverReady <- newEmptyMVar
41+ clientDone <- newEmptyMVar
42+
43+ -- Start the server
44+ forkIO $ do
45+ -- Initialize the server
46+ serverAddr:_ <- getAddrInfo passive Nothing (Just "8080")
47+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
48+ setSocketOption sock ReuseAddr 1
49+ bindSocket sock (addrAddress serverAddr)
50+ listen sock 1
51+
52+ -- Set up multiplexing channel
53+ multiplexMVar <- newEmptyMVar
54+
55+ -- Wait for incoming connections (pings from the client)
56+ putMVar serverReady ()
57+ (clientSock, pingAddr) <- accept sock
58+ forkIO $ socketToMVar clientSock multiplexMVar
59+
60+ -- Reply to the client
61+ forever $ takeMVar multiplexMVar >>= send clientSock
62+
63+ -- Start the client
64+ forkIO $ do
65+ takeMVar serverReady
66+ serverAddr:_ <- getAddrInfo Nothing (Just "127.0.0.1") (Just "8080")
67+ clientSock <- socket (addrFamily serverAddr) Stream defaultProtocol
68+ N.connect clientSock (addrAddress serverAddr)
69+ ping clientSock (read pingsStr)
70+ putMVar clientDone ()
71+
72+ -- Wait for the client to finish
73+ takeMVar clientDone
74+
75+socketToMVar :: Socket -> MVar ByteString -> IO ()
76+socketToMVar sock mvar = go
77+ where
78+ go = do bs <- recv sock
79+ when (BS.length bs > 0) $ do
80+ putMVar mvar bs
81+ go
82+
83+pingMessage :: ByteString
84+pingMessage = pack "ping123"
85+
86+ping :: Socket -> Int -> IO ()
87+ping sock pings = go pings
88+ where
89+ go :: Int -> IO ()
90+ go 0 = do
91+ putStrLn $ "client did " ++ show pings ++ " pings"
92+ go !i = do
93+ before <- getCurrentTime
94+ send sock pingMessage
95+ bs <- recv sock
96+ after <- getCurrentTime
97+ -- putStrLn $ "client received " ++ unpack bs
98+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
99+ hPutStrLn stderr $ show i ++ " " ++ show latency
100+ go (i - 1)
101+
102+-- | Receive a package
103+recv :: Socket -> IO ByteString
104+recv sock = do
105+ header <- NBS.recv sock 4
106+ length <- decodeLength header
107+ NBS.recv sock (fromIntegral (length :: Int32))
108+
109+-- | Send a package
110+send :: Socket -> ByteString -> IO ()
111+send sock bs = do
112+ length <- encodeLength (fromIntegral (BS.length bs))
113+ NBS.sendMany sock [length, bs]
114+
115+-- | Encode length (manual for now)
116+encodeLength :: Int32 -> IO ByteString
117+encodeLength i32 =
118+ BSI.create 4 $ \p ->
119+ pokeByteOff p 0 (htonl (fromIntegral i32))
120+
121+-- | Decode length (manual for now)
122+decodeLength :: ByteString -> IO Int32
123+decodeLength bs =
124+ let (fp, _, _) = BSI.toForeignPtr bs in
125+ withForeignPtr fp $ \p -> do
126+ w32 <- peekByteOff p 0
127+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/JustPingTransport.hsnew file+95
@@ -0,0 +1,95 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import System.Environment (getArgs, withArgs)
9+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
10+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
11+import Control.Concurrent (forkIO)
12+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
13+import qualified Network.Socket as N
14+import Debug.Trace
15+import Data.ByteString (ByteString)
16+import Data.ByteString.Char8 (pack, unpack)
17+import qualified Data.ByteString as BS
18+import qualified Network.Socket.ByteString as NBS
19+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
20+import Network.Transport
21+import Network.Transport.TCP
22+
23+main :: IO ()
24+main = do
25+ [pingsStr] <- getArgs
26+ serverAddr <- newEmptyMVar
27+ clientAddr <- newEmptyMVar
28+ clientDone <- newEmptyMVar
29+
30+ -- Start the server
31+ forkIO $ do
32+ -- establish transport and endpoint
33+ putStrLn "server: creating TCP connection"
34+ Right transport <- createTransport "127.0.0.1" "8080" defaultTCPParameters
35+ Right endpoint <- newEndPoint transport
36+ putMVar serverAddr (address endpoint)
37+
38+ -- Connect to the client so that we can reply
39+ theirAddr <- takeMVar clientAddr
40+ Right conn <- connect endpoint theirAddr ReliableOrdered defaultConnectHints
41+
42+ -- reply to pings with pongs
43+ putStrLn "server: awaiting client connection"
44+ ConnectionOpened _ _ _ <- receive endpoint
45+ pong endpoint conn
46+
47+ -- Start the client
48+ forkIO $ do
49+ let pings = read pingsStr
50+
51+ -- establish transport and endpoint
52+ Right transport <- createTransport "127.0.0.1" "8081" defaultTCPParameters
53+ Right endpoint <- newEndPoint transport
54+ putMVar clientAddr (address endpoint)
55+
56+ -- Connect to the server to send pings
57+ theirAddr <- takeMVar serverAddr
58+ Right conn <- connect endpoint theirAddr ReliableOrdered defaultConnectHints
59+
60+ -- Send pings, waiting for a reply after every ping
61+ ConnectionOpened _ _ _ <- receive endpoint
62+ ping endpoint conn pings
63+ putMVar clientDone ()
64+
65+ -- Wait for the client to finish
66+ takeMVar clientDone
67+
68+pingMessage :: [ByteString]
69+pingMessage = [pack "ping123"]
70+
71+ping :: EndPoint -> Connection -> Int -> IO ()
72+ping endpoint conn pings = go pings
73+ where
74+ go :: Int -> IO ()
75+ go 0 = do
76+ putStrLn $ "client did " ++ show pings ++ " pings"
77+ go !i = do
78+ before <- getCurrentTime
79+ send conn pingMessage
80+ Received _ _payload <- receive endpoint
81+ after <- getCurrentTime
82+ -- putStrLn $ "client received " ++ show _payload
83+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
84+ hPutStrLn stderr $ show i ++ " " ++ show latency
85+ go (i - 1)
86+
87+pong :: EndPoint -> Connection -> IO ()
88+pong endpoint conn = go
89+ where
90+ go = do
91+ msg <- receive endpoint
92+ case msg of
93+ Received _ payload -> send conn payload >> go
94+ ConnectionClosed _ -> return ()
95+ _ -> fail "Unexpected message"
network-transport-tcp/benchmarks/JustPingTwoSocketPairs.hsnew file+151
@@ -0,0 +1,151 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfo, AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr, NoDelay)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
31+
32+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
33+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
34+
35+passive :: Maybe AddrInfo
36+passive = Just (defaultHints { addrFlags = [AI_PASSIVE] })
37+
38+main = do
39+ pingsStr:args <- getArgs
40+ serverReady <- newEmptyMVar
41+ clientReady <- newEmptyMVar
42+ clientDone <- newEmptyMVar
43+
44+ -- Start the server
45+ forkIO $ do
46+ -- Initialize the server
47+ serverAddr:_ <- getAddrInfo passive Nothing (Just "8080")
48+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
49+ setSocketOption sock ReuseAddr 1
50+ bindSocket sock (addrAddress serverAddr)
51+ listen sock 1
52+
53+ -- Set up multiplexing channel
54+ multiplexChannel <- newChan
55+
56+ -- Connect to the client (to reply)
57+ forkIO $ do
58+ takeMVar clientReady
59+ clientAddr:_ <- getAddrInfo Nothing (Just "127.0.0.1") (Just "8081")
60+ pongSock <- socket (addrFamily clientAddr) Stream defaultProtocol
61+ N.connect pongSock (addrAddress clientAddr)
62+ when ("--NoDelay" `elem` args) $ setSocketOption pongSock NoDelay 1
63+ forever $ readChan multiplexChannel >>= send pongSock
64+
65+ -- Wait for incoming connections (pings from the client)
66+ putMVar serverReady ()
67+ (pingSock, pingAddr) <- accept sock
68+ socketToChan pingSock multiplexChannel
69+
70+ -- Start the client
71+ forkIO $ do
72+ clientAddr:_ <- getAddrInfo passive Nothing (Just "8081")
73+ sock <- socket (addrFamily clientAddr) Stream defaultProtocol
74+ setSocketOption sock ReuseAddr 1
75+ bindSocket sock (addrAddress clientAddr)
76+ listen sock 1
77+
78+ -- Set up multiplexing channel
79+ multiplexChannel <- newChan
80+
81+ -- Connect to the server (to send pings)
82+ forkIO $ do
83+ takeMVar serverReady
84+ serverAddr:_ <- getAddrInfo Nothing (Just "127.0.0.1") (Just "8080")
85+ pingSock <- socket (addrFamily serverAddr) Stream defaultProtocol
86+ N.connect pingSock (addrAddress serverAddr)
87+ when ("--NoDelay" `elem` args) $ setSocketOption pingSock NoDelay 1
88+ ping pingSock multiplexChannel (read pingsStr)
89+ putMVar clientDone ()
90+
91+ -- Wait for incoming connections (pongs from the server)
92+ putMVar clientReady ()
93+ (pongSock, pongAddr) <- accept sock
94+ socketToChan pongSock multiplexChannel
95+
96+ -- Wait for the client to finish
97+ takeMVar clientDone
98+
99+socketToChan :: Socket -> Chan ByteString -> IO ()
100+socketToChan sock chan = go
101+ where
102+ go = do bs <- recv sock
103+ when (BS.length bs > 0) $ do
104+ writeChan chan bs
105+ go
106+
107+pingMessage :: ByteString
108+pingMessage = pack "ping123"
109+
110+ping :: Socket -> Chan ByteString -> Int -> IO ()
111+ping sock chan pings = go pings
112+ where
113+ go :: Int -> IO ()
114+ go 0 = do
115+ putStrLn $ "client did " ++ show pings ++ " pings"
116+ go !i = do
117+ before <- getCurrentTime
118+ send sock pingMessage
119+ bs <- readChan chan
120+ after <- getCurrentTime
121+ -- putStrLn $ "client received " ++ unpack bs
122+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
123+ hPutStrLn stderr $ show i ++ " " ++ show latency
124+ go (i - 1)
125+
126+-- | Receive a package
127+recv :: Socket -> IO ByteString
128+recv sock = do
129+ header <- NBS.recv sock 4
130+ length <- decodeLength header
131+ NBS.recv sock (fromIntegral (length :: Int32))
132+
133+-- | Send a package
134+send :: Socket -> ByteString -> IO ()
135+send sock bs = do
136+ length <- encodeLength (fromIntegral (BS.length bs))
137+ NBS.sendMany sock [length, bs]
138+
139+-- | Encode length (manual for now)
140+encodeLength :: Int32 -> IO ByteString
141+encodeLength i32 =
142+ BSI.create 4 $ \p ->
143+ pokeByteOff p 0 (htonl (fromIntegral i32))
144+
145+-- | Decode length (manual for now)
146+decodeLength :: ByteString -> IO Int32
147+decodeLength bs =
148+ let (fp, _, _) = BSI.toForeignPtr bs in
149+ withForeignPtr fp $ \p -> do
150+ w32 <- peekByteOff p 0
151+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/JustPingWithHeader.hsnew file+131
@@ -0,0 +1,131 @@
1+{-# LANGUAGE CPP, BangPatterns #-}
2+
3+module Main where
4+
5+import Control.Monad
6+
7+import Data.Int
8+import Network.Socket
9+ ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10+ , SocketType (Stream), SocketOption (ReuseAddr)
11+ , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
12+ , defaultHints
13+ , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14+import System.Environment (getArgs, withArgs)
15+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16+import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19+import qualified Network.Socket as N
20+import Debug.Trace
21+import Data.ByteString (ByteString)
22+import Data.ByteString.Char8 (pack, unpack)
23+import qualified Data.ByteString as BS
24+import qualified Network.Socket.ByteString as NBS
25+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
30+
31+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
33+
34+main :: IO ()
35+main = do
36+ [pingsStr] <- getArgs
37+ serverReady <- newEmptyMVar
38+ clientDone <- newEmptyMVar
39+
40+ -- Start the server
41+ forkIO $ do
42+ putStrLn "server: creating TCP connection"
43+ serverAddrs <- getAddrInfo
44+ (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
45+ Nothing
46+ (Just "8080")
47+ let serverAddr = head serverAddrs
48+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
49+ setSocketOption sock ReuseAddr 1
50+ bindSocket sock (addrAddress serverAddr)
51+
52+ putStrLn "server: awaiting client connection"
53+ putMVar serverReady ()
54+ listen sock 1
55+ (clientSock, clientAddr) <- accept sock
56+
57+ putStrLn "server: listening for pings"
58+ pong clientSock
59+
60+ -- Start the client
61+ forkIO $ do
62+ takeMVar serverReady
63+ let pings = read pingsStr
64+ serverAddrs <- getAddrInfo
65+ Nothing
66+ (Just "127.0.0.1")
67+ (Just "8080")
68+ let serverAddr = head serverAddrs
69+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
70+
71+ N.connect sock (addrAddress serverAddr)
72+
73+ ping sock pings
74+ putMVar clientDone ()
75+
76+ -- Wait for the client to finish
77+ takeMVar clientDone
78+
79+pingMessage :: ByteString
80+pingMessage = pack "ping123"
81+
82+ping :: Socket -> Int -> IO ()
83+ping sock pings = go pings
84+ where
85+ go :: Int -> IO ()
86+ go 0 = do
87+ putStrLn $ "client did " ++ show pings ++ " pings"
88+ go !i = do
89+ before <- getCurrentTime
90+ send sock pingMessage
91+ bs <- recv sock 8
92+ after <- getCurrentTime
93+ -- putStrLn $ "client received " ++ unpack bs
94+ let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
95+ hPutStrLn stderr $ show i ++ " " ++ show latency
96+ go (i - 1)
97+
98+pong :: Socket -> IO ()
99+pong sock = do
100+ bs <- recv sock 8
101+ -- putStrLn $ "server received " ++ unpack bs
102+ when (BS.length bs > 0) $ do
103+ send sock bs
104+ pong sock
105+
106+-- | Wrapper around NBS.recv (for profiling)
107+recv :: Socket -> Int -> IO ByteString
108+recv sock _ = do
109+ header <- NBS.recv sock 4
110+ length <- decodeLength header
111+ NBS.recv sock (fromIntegral (length :: Int32))
112+
113+-- | Wrapper around NBS.send (for profiling)
114+send :: Socket -> ByteString -> IO ()
115+send sock bs = do
116+ length <- encodeLength (fromIntegral (BS.length bs))
117+ NBS.sendMany sock [length, bs]
118+
119+-- | Encode length (manual for now)
120+encodeLength :: Int32 -> IO ByteString
121+encodeLength i32 =
122+ BSI.create 4 $ \p ->
123+ pokeByteOff p 0 (htonl (fromIntegral i32))
124+
125+-- | Decode length (manual for now)
126+decodeLength :: ByteString -> IO Int32
127+decodeLength bs =
128+ let (fp, _, _) = BSI.toForeignPtr bs in
129+ withForeignPtr fp $ \p -> do
130+ w32 <- peekByteOff p 0
131+ return (fromIntegral (ntohl w32))
network-transport-tcp/benchmarks/Makefilenew file+55
@@ -0,0 +1,55 @@
1+# The "Just Ping" tests measure ping latency with as little overhead as possible
2+
3+NUMPINGS=100000
4+ROOT=../..
5+INCLUDES=-i${ROOT}/network-transport/src -i${ROOT}/network-transport-tcp/src
6+
7+# Enable for profiling
8+# PROF_GHC=-prof -fprof-auto
9+# PROF_EXE=+RTS -pa -RTS
10+
11+GCC=gcc -std=c99
12+GHC=ghc -rtsopts -XRankNTypes -XScopedTypeVariables -XDeriveDataTypeable -XCPP -XGeneralizedNewtypeDeriving -optP-include -optPcabal_macros.h
13+
14+all: NewTransport.ps Indirection.ps Headers.ps
15+
16+NewTransport.ps: JustPingHaskell.data \
17+ JustPingTransport.data
18+ gnuplot ./NewTransport.gnuplot
19+
20+Indirection.ps: JustPingWithHeader.data \
21+ JustPingThroughChan.data \
22+ JustPingThroughMVar.data \
23+ JustPingTwoSocketPairs.data \
24+ JustPingTwoSocketPairsND.data \
25+ JustPingTransport.data
26+ gnuplot ./Indirection.gnuplot
27+
28+Headers.ps: JustPingC.data \
29+ JustPingHaskellNT.data \
30+ JustPingHaskell.data \
31+ JustPingWithHeader.data \
32+ JustPingOneRecv.data \
33+ JustPingCacheHeader.data
34+ gnuplot ./Headers.gnuplot
35+
36+JustPingC.exe: JustPingC.c
37+ $(GCC) -O2 -o JustPingC.exe JustPingC.c
38+
39+JustPingHaskellNT.exe: JustPingHaskell.hs
40+ $(GHC) -O2 $(PROF_GHC) -o JustPingHaskellNT.exe JustPingHaskell.hs
41+
42+JustPingTwoSocketPairsND.data: JustPingTwoSocketPairs.exe
43+ time ./$< $(NUMPINGS) --NoDelay $(PROF_EXE) 2>$@
44+
45+%.data : %.exe
46+ time ./$< $(NUMPINGS) $(PROF_EXE) 2>$@
47+
48+%.exe :: %.hs
49+ $(GHC) -O2 $(PROF_GHC) -threaded -o $@ --make $< $(INCLUDES)
50+
51+.PHONY: clean
52+clean:
53+ rm -f *.data *.ps *.pdf *.o *.hi *.exe
54+
55+# vi:set noexpandtab:
network-transport-tcp/benchmarks/NewTransport.gnuplotnew file+8
@@ -0,0 +1,8 @@
1+set title "Roundtrip (us)"
2+set yrange [0:150]
3+plot "JustPingHaskell.data" smooth bezier with lines title "JustPingHaskell", \
4+ "JustPingTransport.data" smooth bezier with lines title "JustPingTransport"
5+set terminal postscript color
6+set output "NewTransport.ps"
7+plot "JustPingHaskell.data" smooth bezier with lines title "JustPingHaskell", \
8+ "JustPingTransport.data" smooth bezier with lines title "JustPingTransport"
network-transport-tcp/benchmarks/cabal_macros.hnew file+5
@@ -0,0 +1,5 @@
1+#define VERSION_base "4.5.0.0"
2+#define MIN_VERSION_base(major1,major2,minor) (\
3+ (major1) < 4 || \
4+ (major1) == 4 && (major2) < 5 || \
5+ (major1) == 4 && (major2) == 5 && (minor) <= 0)