Napisałem bibliotekę o nazwie amqp-worker, która udostępnia funkcję o nazwie worker
, która odpytuje kolejkę wiadomości (np. RabbitMQ) dla wiadomości, wywołując procedurę obsługi po znalezieniu wiadomości. Następnie wraca do odpytywania.Usterka pamięci w rekurencyjnej funkcji IO - PAP
To cieknąca pamięć. Wyprofilowałem go, a na wykresie jest napisane, że sprawcą jest aplikacja o częściowym działaniu. Gdzie jest wyciek z mojego kodu? Jak mogę uniknąć nieszczelności podczas zapętlenia w IO
z forever
?
Oto kilka istotnych funkcji. The full source is here.
Example Program. Jest to wyciek
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
Co twoja wersja ghc i jak się kompilujesz? – jberryman
Jest ustawiony na lts-7.3, więc jest to GHC 8.0.1. Kompiluję z instalacją stosu --profile. Ale mam wyciek pamięci przy normalnej instalacji stosu. Używanie domyślnych opcji GHC z szablonu stosu: -threaded -rtsopts -with-rtsopts = -N –
Ten przykład jest bardzo daleki od minimalnego - importujesz całą swoją bibliotekę ('Network.AMQP.Worker') w swoim przykładowym programie. W obecnej formie jest to zbyt szeroki zakres. – user2407038