我的程序在 IO
中使用 GHC API,在 GhcMonad
内部执行一些计算,并在返回结果之前强制执行结果;大致像这样:
main :: IO ()
main = do
x <- runGhcT $ do
x0 <- someGhcFunctionality
x1 <- furtherProcessing
liftIO . evaluate . force $ x1
putStrLn "Done with GHC."
_ <- getLine
continueProcessingOutsideGhc x
在暂停点,我可以看到该进程使用了30GB+的RAM;由于continueProcessingOutsideGhc
也会占用一定量的内存,因此这可能导致在continueProcessingOutsideGhc
中途内存不足。
然而,我发现在暂停点手动强制进行垃圾回收可以显著改变情况:
import System.Mem
main :: IO ()
main = do
x <- runGhcT $ do
x0 <- someGhcFunctionality
x1 <- furtherProcessing
liftIO . evaluate . force $ x1
putStrLn "Done with GHC."
_ <- getLine
performGC
putStrLn "Done with performGC."
_ <- getLine
continueProcessingOutsideGhc x
那个 `performGC` 行将内存占用减少了85%,约为4GB。这当然足够让 `continueProcessingOutsideGhc` 完成任务。应该注意的是,在 `runGhcT` 中执行 `liftIO performGC` 没有同样的效果;我猜这很有道理,如果全局GHC上下文保留了很多东西。
我想要理解的是,为什么在没有手动执行 `performGC` 的情况下退出 `runGhcT` 后所有的垃圾都会留在那里。
continueProcessingOutsideGhc
中内存不足。”你有观察到这种情况发生了吗,还是你只是担心它可能会发生?我和Daniel Wagner一样怀疑:GC应该根据需要运行,因此无论你是否进行GC,continueProcessingOutsideGhc
都应该成功。如果你可以证明performGC
实际上可靠地影响是否会出现内存不足,那将是一个有趣的错误跟踪(对于比我更有专业知识的人)。 - amalloycontinueProcessingOutsideGhc
期间出现内存不足的情况确实经常发生。这就是我首先进行performGC
操作的原因。 - Cactus