Note that there are some explanatory texts on larger screens.

plurals
  1. POHaskell - Slow socket connection when threaded
    primarykey
    data
    text
    <p>I've started with Haskell a while ago and now I'm focusing on networking. I followed some tutorials and source samples to put together a very simple echo server:</p> <pre><code>main = withSocketsDo $ do forkIO $ acceptor 8080 print "Server running ... " &gt;&gt; getLine &gt;&gt;= print tcpSock :: IO Socket tcpSock = socket AF_INET Stream 0 acceptor :: PortNumber -&gt; IO () acceptor port = do -- Setup server socket sock &lt;- tcpSock setSocketOption sock ReuseAddr 1 bindSocket sock (SockAddrInet port iNADDR_ANY) listen sock 50 -- Start with zero index loop sock 0 where loop sock sockId = do -- Accept socket (nextSock, addr) &lt;- accept sock -- Setup the socket for performance (_, handle) &lt;- setupClient nextSock -- Run client in own thread forkIO $ do -- Get a stream of bytes stream &lt;- BS.hGetContents handle -- Echo the first received char BS.hPut handle $ BS.take 1 stream -- Kill the socket SIO.hClose handle -- Accept next client loop sock (sockId + 1) setupClient :: Socket -&gt; IO (Socket, SIO.Handle) setupClient sock = do -- Disable nagle setSocketOption sock NoDelay 1 -- Disable buffering hdl &lt;- socketToHandle sock SIO.ReadWriteMode SIO.hSetBuffering hdl SIO.NoBuffering return (sock, hdl) </code></pre> <p>Now, I've tested the code with the ab-Tool to benchmark the server. The code is compiled using -O2 and -threaded and the program is started using +RTS -N to use multiple OS threads.</p> <p>The code creates a new lightweight thread per client and as far as I remember are these threads pretty cheap because they are scheduled by a bunch of real OS threads.</p> <p>After running the tool, the results are:</p> <p>ab -n 10000 -c 1000 <code>http://localhost:8080/</code> ~ 500 - 1600 req/sec Yes, it does change sometimes between 500 and 1600!</p> <p>At first I thought well, not bad. Then I ran the program without "+RTS -N" and results are almost every time ~20000 req/sec.</p> <p>Obviously the threading kills the performance pretty badly, but why ? My guess is, that the IO manager does a pretty bad job when dealing with a lot of connections.</p> <p>BTW: I use Ubuntu 13.04 and ghc 7.6, but I've tested the code under Windows 8 which gave me far worse results, but I think the IO manager is tuned for linux, which makes sense.</p> <p>Am I doing something reallly stupid here ?? I know, the example is quite trivial but here is obviously something going wrong.</p> <p>Regards, Chris</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload