4

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

首先,我分叉了接受方法并回显所有传入的消息。我已经使用 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
4

1 回答 1

6

我刚刚和一位同事谈过,他告诉我问题出在这部分

loop sock (sockId + 1)

我在没有评估的情况下建立了 thunk,这肯定会填满堆。我希望这可以帮助其他面临类似问题的人。

于 2013-06-18T12:06:30.307 回答