4

我正在玩一些基本的哈斯克爾網絡的東西,但有一個問題 這促使我堅果。以下相當簡單的服務器代碼似乎泄漏了內存,我只是不知道爲什麼。哈斯克爾套接字編程 - 內存泄漏

首先,我爲接受方法分叉,然後回覆所有傳入的消息。我已經使用Apache基準測試工具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 
+0

ghc版本和網絡包的版本?正如我上面提到的那樣,GHC 7.6是 – Jonke

+0

。網絡包2.4.1.2(最新) – Kr0e

+0

一個小提示,閱讀http://www.haskell.org/haskellwiki/Simple_Servers和這個http://www.haskell.org/haskellwiki/Implement_a_chat_server – Jonke

回答

6

我剛剛講一個同事,他告訴我,這個問題是本節

loop sock (sockId + 1) 

我buildung起來的thunk而沒有evaluting,這無疑填補了堆。 我希望這可以幫助其他人面臨類似的問題。

+1

是的,'sockId'是從來沒有使用過,所以編譯器沒有理由評估'sockId + 1'。 –

+4

理論上,編譯器在發現它不被使用時甚至不應該自己生成thunk;) – Ankur

+0

你是否編譯過優化? – jberryman