git.iko.soy/distributed-process
on master help sign in
Run server and client inside a single process

This means we can do better profiling

commit90cb954fbab4c5ef71d6c320b5ddcf7eab0f477c authorEdsko de Vries <edsko@well-typed.com> dateWed 11 Apr 2012, 15:32 (15 years ago) parent39d8085
3 files changed+88−74
benchmarks/PingTCP.hs+38−32 benchmarks/PingTCPTransport.hs+39−36 benchmarks/pingtest.c+11−6
benchmarks/PingTCP.hs+38−32
@@ -16,6 +16,8 @@ import Network.Socket
1616import System.Environment (getArgs, withArgs)
1717import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
1818import System.IO (withFile, IOMode(..), hPutStrLn)
19+import Control.Concurrent (forkIO)
20+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
1921
2022import qualified Network.Socket as N
2123
@@ -56,38 +58,42 @@ decode :: Ser.Serialize a => ByteString -> Either String a
5658-- The server must be restarted between benchmarks.
5759main :: IO ()
5860main = do
59− args <- getArgs
60− case args of
61− "server" : service : [] -> withSocketsDo $ do
62− putStrLn "server: creating TCP connection"
63− serverAddrs <- getAddrInfo
64− (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
65− Nothing
66− (Just service)
67− let serverAddr = head serverAddrs
68− sock <- socket (addrFamily serverAddr) Stream defaultProtocol
69− setSocketOption sock ReuseAddr 1
70− bindSocket sock (addrAddress serverAddr)
71−
72− putStrLn "server: awaiting client connection"
73− listen sock 1
74− (clientSock, clientAddr) <- accept sock
75−
76− putStrLn "server: listening for pings"
77− pong clientSock
78−
79− "client": host : service : pingsStr : [] -> withSocketsDo $ do
80− let pings = read pingsStr
81− serverAddrs <- getAddrInfo
82− Nothing
83− (Just host)
84− (Just service)
85− let serverAddr = head serverAddrs
86− sock <- socket (addrFamily serverAddr) Stream defaultProtocol
87−
88− N.connect sock (addrAddress serverAddr)
89−
90− ping sock pings
61+ [pingsStr] <- getArgs
62+ serverReady <- newEmptyMVar
63+
64+ -- Start the server
65+ forkIO $ do
66+ putStrLn "server: creating TCP connection"
67+ serverAddrs <- getAddrInfo
68+ (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
69+ Nothing
70+ (Just "8080")
71+ let serverAddr = head serverAddrs
72+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
73+ setSocketOption sock ReuseAddr 1
74+ bindSocket sock (addrAddress serverAddr)
75+
76+ putStrLn "server: awaiting client connection"
77+ putMVar serverReady ()
78+ listen sock 1
79+ (clientSock, clientAddr) <- accept sock
80+
81+ putStrLn "server: listening for pings"
82+ pong clientSock
83+
84+ -- Client
85+ takeMVar serverReady
86+ let pings = read pingsStr
87+ serverAddrs <- getAddrInfo
88+ Nothing
89+ (Just "127.0.0.1")
90+ (Just "8080")
91+ let serverAddr = head serverAddrs
92+ sock <- socket (addrFamily serverAddr) Stream defaultProtocol
93+
94+ N.connect sock (addrAddress serverAddr)
95+
96+ ping sock pings
9197
9298pingMessage :: ByteString
9399pingMessage = pack "ping123"
benchmarks/PingTCPTransport.hs+39−36
@@ -14,6 +14,8 @@ import Data.Int
1414import System.Environment (getArgs, withArgs)
1515import Data.Time (getCurrentTime, diffUTCTime)
1616import System.IO (withFile, IOMode(..), hPutStrLn)
17+import Control.Concurrent (forkIO)
18+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
1719
1820#ifndef LAZY
1921import qualified Data.ByteString.Char8 as BS
@@ -50,42 +52,43 @@ decode :: Ser.Serialize a => BS.ByteString -> Either String a
5052-- The server must be restarted between benchmarks.
5153main :: IO ()
5254main = do
53− args <- getArgs
54− case args of
55− "server" : host : service : sourceAddrFilePath : [] -> do
56− -- establish transport
57− transport <- mkTransport $ TCPConfig defaultHints host service
58−
59− -- create ping end
60− putStrLn "server: creating ping end"
61− (sourceAddrPing, targetEndPing) <- newConnection transport
62− BS.writeFile sourceAddrFilePath $ serialize sourceAddrPing
63−
64− -- create pong end
65− putStrLn "server: creating pong end"
66− [sourceAddrPongBS] <- receive targetEndPing
67− sourceEndPong <- connect . fromJust $ deserialize transport sourceAddrPongBS
68−
69− -- always respond to a ping with a pong
70− putStrLn "server: awaiting pings"
71− pong targetEndPing sourceEndPong
72−
73−
74− "client" : host : service : sourceAddrFilePath : pingsStr : [] -> do
75− let pings = read pingsStr
76− -- establish transport
77− transport <- mkTransport $ TCPConfig defaultHints host service
78−
79− -- create ping end
80− sourceAddrPingBS <- BS.readFile sourceAddrFilePath
81− sourceEndPing <- connect . fromJust $ deserialize transport sourceAddrPingBS
82−
83− -- create pong end
84− (sourceAddrPong, targetEndPong) <- newConnection transport
85− send sourceEndPing [serialize sourceAddrPong]
86−
87− ping sourceEndPing targetEndPong pings
88− putStrLn "Done with all ping/pongs."
55+ [pingsStr] <- getArgs
56+ serverReady <- newEmptyMVar
57+
58+ -- Start the server
59+ forkIO $ do
60+ -- establish transport
61+ transport <- mkTransport $ TCPConfig defaultHints "127.0.0.1" "8080"
62+
63+ -- create ping end
64+ putStrLn "server: creating ping end"
65+ (sourceAddrPing, targetEndPing) <- newConnection transport
66+ putMVar serverReady sourceAddrPing
67+
68+ -- create pong end
69+ putStrLn "server: creating pong end"
70+ [sourceAddrPongBS] <- receive targetEndPing
71+ sourceEndPong <- connect . fromJust $ deserialize transport sourceAddrPongBS
72+
73+ -- always respond to a ping with a pong
74+ putStrLn "server: awaiting pings"
75+ pong targetEndPing sourceEndPong
76+
77+ -- Client
78+ sourceAddr <- takeMVar serverReady
79+ let pings = read pingsStr
80+ -- establish transport
81+ transport <- mkTransport $ TCPConfig defaultHints "127.0.0.1" "8081"
82+
83+ -- create ping end
84+ sourceEndPing <- connect sourceAddr
85+
86+ -- create pong end
87+ (sourceAddrPong, targetEndPong) <- newConnection transport
88+ send sourceEndPing [serialize sourceAddrPong]
89+
90+ ping sourceEndPing targetEndPong pings
91+ putStrLn "Done with all ping/pongs."
8992
9093-- | The message we use to ping (CAF so that we don't keep encoding it)
9194pingMessage :: BS.ByteString
benchmarks/pingtest.c+11−6
@@ -39,6 +39,8 @@ double timestamp() {
3939}
4040
4141int server() {
42+ printf("starting server\n");
43+
4244 struct addrinfo hints, *res;
4345 int error, server_socket;
4446
@@ -161,18 +163,21 @@ int client(int pings) {
161163}
162164
163165int usage(int argc, char** argv) {
164− printf("usage: %s server or %s client <number of pings>\n", argv[0], argv[0]);
166+ printf("usage: %s <number of pings>\n", argv[0]);
165167 return -1;
166168}
167169
168170int main(int argc, char** argv) {
169− if(argc == 2 && !strcmp(argv[1], "server")) {
170− return server();
171− } else if(argc == 3 && !strcmp(argv[1], "client")) {
171+ if(argc != 2) {
172+ return usage(argc, argv);
173+ }
174+
175+ if(fork() == 0) {
176+ // TODO: we should wait until we know the server is ready
172177 int pings = 0;
173− sscanf(argv[2], "%d", &pings);
178+ sscanf(argv[1], "%d", &pings);
174179 return client(pings);
175180 } else {
176− return usage(argc, argv);
181+ return server();
177182 }
178183}