Haskell套接字编程 - 内存泄漏

Kr0*_*r0e 4 networking garbage-collection haskell memory-leaks lazy-evaluation

我正在玩一些基本的haskell网络的东西,但有一个问题让我疯了.以下非常简单的服务器代码似乎泄漏内存,我只是不知道为什么.

首先,我分叉accept方法,只是回显所有传入的消息.我用Apache Benchmark Tool ab测试了服务器.但经过几次使用ab的测试后,服务器进程开始泄漏内存,但不是很多,而是持续不断.我估计每10000个请求大约1 MB.

问题是:这是某种内部垃圾收集器优化还是确实泄漏内存?我已经测试了程序高达200 MB的内存使用量,仍然在增长.

在这个例子中,我使用严格的ByteStrings.我做的另一个测试是使用基于句柄的IO,这并没有导致内存总共超过3 MB.

使用惰性IO(ByteString.Lazy)导致了同样的问题,但速度更快.我正在使用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
Run Code Online (Sandbox Code Playgroud)

Kr0*_*r0e 6

我刚跟一位同事说过,他告诉我问题就在这一部分

loop sock (sockId + 1)
Run Code Online (Sandbox Code Playgroud)

我在没有评估的情况下积累了thunk,这肯定会填满堆.我希望这有助于其他人面临类似的问题.

  • 从理论上讲,编译器在发现它没有被使用时甚至不应该自己生成thunk;) (4认同)