というライブラリを作成しました。worker
という関数を提供し、メッセージが見つかったときにハンドラを呼び出して、メッセージキュー(RabbitMQなど)をポーリングします。それからポーリングに戻ります。再帰的IO関数のメモリリーク - PAP
メモリがリークしています。私はそれをプロファイリングし、グラフはPAP
(部分関数アプリケーション)が原因だと言います。 私のコードのどこに漏れがありますか? IO
でループするときに、漏れを避けるにはどうすればいいですか?forever
?ここで
いくつかの関連する機能があります。 The full source is here。
Example Program。これは、メモリリークがpoll
であっ
main :: IO()
main = do
-- connect
conn <- Worker.connect (fromURI "amqp://guest:[email protected]:5672")
-- initialize the queues
Worker.initQueue conn queue
Worker.initQueue conn results
-- publish a message
Worker.publish conn queue (TestMessage "hello world")
-- create a worker, the program loops here
Worker.worker def conn queue onError (onMessage conn)
worker :: (FromJSON a, MonadBaseControl IO m, MonadCatch m) => WorkerOptions -> Connection -> Queue key a -> (WorkerException SomeException -> m()) -> (Message a -> m()) -> m()
worker opts conn queue onError action =
forever $ do
eres <- consumeNext (pollDelay opts) conn queue
case eres of
Error (ParseError reason bd) ->
onError (MessageParseError bd reason)
Parsed msg ->
catch
(action msg)
(onError . OtherException (body msg))
liftBase $ threadDelay (loopDelay opts)
consumeNext :: (FromJSON msg, MonadBaseControl IO m) => Microseconds -> Connection -> Queue key msg -> m (ConsumeResult msg)
consumeNext pd conn queue =
poll pd $ consume conn queue
poll :: (MonadBaseControl IO m) => Int -> m (Maybe a) -> m a
poll us action = do
ma <- action
case ma of
Just a -> return a
Nothing -> do
liftBase $ threadDelay us
poll us action
散策あなたのghcのバージョンとはどのようにコンパイルしていますか? – jberryman
これはlts-7.3に設定されているので、GHC 8.0.1です。私はstack install --profileでコンパイルしています。しかし、私は通常のスタックのインストールでメモリリークを取得します。スタックテンプレートのデフォルトのghcオプションを使用する:-threaded -rtsopts -with-rtsopts = -N –
この例は非常に遠くありません。サンプルプログラムでライブラリ全体( 'Network.AMQP.Worker')をインポートしています。それがそうであるように、これは広すぎます。 – user2407038