Во-первых, я извиняюсь за то, что у меня нет минимального примера (я могу попытаться построить его, но пока у меня есть пример до и после):
Сначала после чего происходит утечка памяти:
protoReceiver :: RIO FdsEnv ()
protoReceiver = do
logItS Info ["Entering FarmPCMessage protoReceiver"]
tMap <- liftIO $ newThreadMap
fdsEnv <- ask
let lgr = fdsLogger fdsEnv
loopBody <- pure $ bracketOnError
(runResourceT $ protoServe fdsEnv tMap readFarmPCMessage)
(\(_,w) -> do
logLogItS Debug lgr ["Entering cleanup for protoReceiver"]
)
(\(server,_) -> do
logLogItS Debug lgr ["Entering FarmPCMessage protoReceiver bracket"]
server
.| mapMC (liftIO . traverse_ (persistFarmEntry fdsEnv))
.| mapMC ((logLogIt Info lgr) . pure)
.| sinkUnits & runConduitRes
)
liftIO loopBody
Вот предыдущий код, который не допускает утечки памяти:
protoReceiver :: RIO FdsEnv ()
protoReceiver = do
logItS Info ["Entering FarmPCMessage protoReceiver"]
tMap <- liftIO $ newThreadMap
fdsEnv <- ask
let lgr = fdsLogger fdsEnv
(dmgrProtoServe, tcpWorker) <- liftIO $ runResourceT
$ protoServe fdsEnv tMap readFarmPCMessage
liftIO $ runResourceT $ dmgrProtoServe
.| mapMC (liftIO . traverse_ (persistFarmEntry fdsEnv))
.| mapMC ((logLogIt Info lgr) . pure)
.| sinkUnits & runConduit
Я сделал некоторое профилирование утечки, хотя я не уверен, что это особенно полезно (любые предложения по улучшению диаграмм профилирования приветствуются):
server
сохраняется дольше, чем должно, потому что оно должно быть передано обработчику исключений в случае ошибки. Я бы попробовал взломать/поэкспериментировать только с прямым возвратомw
из действия выделения и передать значениеserver
в тело цикла, используя вместо этогоMVar
. - person danidiaz   schedule 24.09.2020