Kr0e
Kr0e

Reputation: 2239

Haskell socket programming - Memory leaks

I'm playing with some basic haskell network stuff but there is a problem which drives me nuts. The following quite simple server code seems to leak memory and I just don't know why.

First I fork the accept-method and just echo all incoming messages. I've tested the server with the Apache Benchmark Tool ab. But after a few tests using ab the server process starts to leak memory, not much but continuously. I would guess roughly 1 MB every 10000 requests.

The question is: Is this some kind of internal Garbage Collector optimization or does it indeed leak memory ? I've tested the program up to 200 MB memory usage, still growing.

In this example I'm using strict ByteStrings. Another test I did was using handle-based IO, which didn't caused the memory to grow over 3 MB in total.

Using lazy IO (ByteString.Lazy) caused the same problem but even faster. I'm using GHC 7.6 (Windows 8).

echoClient :: Socket -> IO ()
echoClient nextSock = do
    -- Get a stream of bytes
    stream <- NetStrictBS.recv nextSock 120

    -- Echo back
    NetStrictBS.send nextSock stream

    -- Kill the socket
    sClose nextSock


acceptClients :: Socket -> IO ()
acceptClients sock = do

    -- Start with zero index
    loop sock 0
        where

        loop sock sockId = do
            -- Accept socket
            (nextSock, addr) <- accept sock

            -- Disable Nagle
            setSocketOption nextSock NoDelay 1

            -- Process client
            echoClient nextSock

            -- Accept next client
            loop sock (sockId + 1)


main = withSocketsDo $ do

    -- Setup server socket
    sock <- tcpSock
    setSocketOption sock ReuseAddr 1
    bindSocket sock (SockAddrInet 1337 iNADDR_ANY)
    listen sock 128

    -- Fork the acceptor
    forkIO $ acceptClients sock

    print "Server running ... " >> getLine >>= print

Upvotes: 4

Views: 785

Answers (1)

Kr0e
Kr0e

Reputation: 2239

I've just spoke to an colleague and he told me that the problem is this section

loop sock (sockId + 1)

I'm buildung up thunks without ever evaluting, which definitely fills up the heap. I hope this helps other people facing similiar problems.

Upvotes: 6

Related Questions