2011-02-18 84 views
4

讓我把我的問題簡單如下。 Mine是在erlang中構建的網絡路由器軟件,但在特定情況下,我正在觀察VM顯示的非常高的內存增長。 在Erlang應用程序中觀察到的內存泄漏

我有一個進程從套接字的某個其他進程接收二進制包。

這個過程中,解析二進制分組和經過二進制分組到gen_server(handle_cast稱)

的gen_server再次存儲在ETS表中的一些信息,並且將數據包發送給對等服務器。

當對等服務器返回響應從所述ETS的條目被刪除,gen_server返回響應所述第一過程

此外,如果第一進程(其發送的分組到gen_server)5秒後獲取已逾時等待來自gen_server響應它也會刪除gen_server中的ETS條目並退出。

現在我觀察,當大量的事件被超時(由於對等服務器不可用)高內存增長,從我已經研究其對「** **的二進制」和「** processes_used **「由erlang給出:使用大部分內存的內存命令。

但事件處理成功時情況並非如此。

+0

因此,看起來你有一個錯誤,當事件超時。你有什麼問題? – 2011-02-18 06:54:25

+0

在超時期間觀察到的內存增長是我的問題。不知道爲什麼二進制大小增長,即使我沒有在任何進程中存儲二進制文件。我只是在UDP收到它們後立即發送事件。似乎引用計數的二進制文件被複制,不能被垃圾收集......但爲什麼只有超時? – Arunmu 2011-02-18 06:58:41

回答

7

失去基本可以存儲只在三個地方:

  1. 您gen_server

    • 看看你的狀態,找出是否有一些大的或增長的東西有
    • 的狀態
  2. 你的過程郵箱

    • 看到它有一些方法來總是消耗不匹配的消息(對於gen_server handle_info回調)在正常的receive條款Any ->條款。

    • 如果郵箱只是暫時填滿它,可能是因爲接收過程對於生成的郵件的速率太慢。這通常是異步通信的問題。如果它唯一的暫時性爆發不會破壞任何這些可能是有意的。

      • 在這種情況下,您可以優化接收過程

      • 或修復您的協議使用更少的消息

      • 如果你有收到一些郵件多種功能,確保所有接收部分被定期打電話。不要忘記Any ->子句。

    • 要知道,當你在一個gen_servers處理回調沒有消息會被接受,所以如果你需要更多的時間回調,這將是必要的asyncronous消息可能會堆積起來(例如,隨機消息的到達+固定處理時間建立一個無界日益增長的隊列,詳見Queueing theory

  3. 在你ETS表

    • 也許信息在ETS中是不是完全刪除?在某些情況下忘記刪除某些內容?
3

很有可能您正在運行的引用了二進制文件的進程正在運行。如果某個進程死亡,則與該進程相關的所有內存都將被清除(包括僅屬於該進程的任何二進制文件)。

如果你仍然有泄漏的二進制文件,這意味着你有一些長時間運行的進程(服務器,單例等),它保持對二進制文件的引用,無論是處理狀態還是非尾遞歸函數。確保在過程通信超時或死亡時清除狀態。此外,請檢查您是否不使用非尾遞歸調用在堆上留下對二進制文件的引用。

+0

@Adam:謝謝。你很接近答案。它是顯示大量內存的gen server。任何想法如何清理引用的二進制文件? – Arunmu 2011-02-18 10:56:37

+1

@ArunMu:在未來的狀態下停止引用它們,例如通過將狀態向量記錄中的字段設置爲未定義的或甚至是新的二進制文件。 – 2011-02-18 12:23:17

7

手動觸發GC,看看內存發生了什麼。

[garbage_collect(Pid) || Pid <- processes()]