私はいくつかの基本的な haskell ネットワークで遊んでいますが、私を夢中にさせる問題があります。次の非常に単純なサーバー コードでは、メモリ リークが発生しているように見えますが、その理由はわかりません。
まず、accept-method を fork し、すべての受信メッセージをエコーします。サーバーを Apache Benchmark Tool ab でテストしました。しかし、ab を使用していくつかのテストを行った後、サーバー プロセスでメモリ リークが発生し始めました。10000 リクエストごとに約 1 MB だと思います。
問題は、これはある種の内部ガベージ コレクターの最適化なのか、それとも実際にメモリ リークなのかということです。プログラムを最大 200 MB のメモリ使用量でテストしましたが、まだ増加しています。
この例では、厳密な ByteString を使用しています。私が行った別のテストでは、ハンドルベースの 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