我有一個程式顯示記憶體泄漏的行為。它逐漸占用所有系統記憶體,直到填滿所有交換空間,然后作業系統將其殺死。這種情況每隔幾天發生一次。
我已經以某種方式(-hy、-hm、-hc)廣泛地分析了堆并嘗試限制堆大小(-M128M)調整代數(-G1)但無論我做什么堆大小似乎都是恒定的-ish 和低總是(以 kB 而非 MB 或 GB 為單位)。然而,當我在 htop 中觀察該程式時,其駐留記憶體穩步上升。
這向我表明記憶體泄漏來自 GHC 堆以外的其他地方。我的程式利用了依賴項,特別是yaml
封裝了 C 庫的Haskell庫libyaml
,泄漏可能在于它具有的指向分配的物件的外部指標的數量libyaml
。
我的問題有三個:
- 在 Haskell 程式中,除了 GHC 堆之外,還有哪些地方會發生記憶體泄漏?
- 我可以使用哪些工具來追蹤這些?
- 需要對我的源代碼進行哪些更改以避免這些型別的泄漏,因為它們似乎與 Haskell 中更常見的空間泄漏不同?
uj5u.com熱心網友回復:
這當然聽起來像外部指標沒有正確完成。這有幾個可能的原因:
- 底層 C 庫沒有正確釋放記憶體。
- Haskell 庫沒有正確設定終結。
- 該
ForeignPtr
物件不會被釋放。
我認為它實際上很有可能是選項 3。如果 RTS 在第一代 GC 中始終找到足夠的記憶體,那么它就不會費心運行主要收集。幸運的是,這是最容易診斷的。只是讓你的程式System.Memory.performGC
經常運行。如果修復了它,您就找到了錯誤,并且可以調整您想要這樣做的頻率。
另一個可能的問題是,您可能會在長期存在的 thunk 或其他閉包中存在外部指標。確保你沒有。
使用包裝的 C 庫時,一種特別強烈的可能性是包裝函式將回傳ByteString
其底層陣列由 C 代碼分配的 s。所以ByteString
你得到的任何syaml
都可能是堆外的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/392569.html