python 記憶體泄露的診斷

來源:互聯網
上載者:User

 

對於一個用 python 實現的,長期啟動並執行後台服務進程來說,如果記憶體持續增長,那麼很可能是有了“記憶體泄露”

 

一、記憶體泄露的原因

對於 python 這種支援記憶體回收的語言來說,怎麼還會有記憶體泄露? 概括來說,有以下三種原因:

 

1、 所用到的用 C 語言開發的底層模組中出現了記憶體泄露。

2、 代碼中用到了全域的 list、 dict 或其它容器,不停的往這些容器中插入對象,而忘記了在使用完之後進行刪除回收

3、 代碼中有“引用迴圈”, python 垃圾處理機制無法進行回收

 

 

二、 記憶體泄露的診斷思路

 

無論是哪種方式的記憶體泄露,最終表現的形式都是某些 python 對象在不停的增長;因此,首先是要找到這些異常的對象。

 

三、 記憶體泄露的診斷步驟

 

用到的工具: gc 模組和 objgraph

objgraph 是一個用於診斷記憶體問題的有用的工具

 

 

1、 在服務程式的迴圈邏輯中,選擇出一個診斷點

 

 

2、 在診斷點,插入如下診斷語句

 

 

import gc<br />import objgraph<br />### 強制進行記憶體回收<br />gc.collect()<br />### 列印出對象數目最多的 50 個類型資訊<br />objgraph.show_most_common_types(limit=50) 

 

 

3、 檢查統計資訊,找到異常對象。

 

運行加入診斷語句的服務程式,並將列印到螢幕上的統計資訊重新導向到日誌中。

運行一段時間後,就可以來分析日誌,看看哪些對象在不停的增長。

 

以我的有問題的程式為例,我將日誌記錄到 log.txt 中,運行一段時間後,發現 tuple 和 list 類型的對象不停增長:

 

# grep "^list " log.txt

# grep "^tuple " log.txt

 

由於 tuple 和 list 是一種通用的類型,因此,那些不停增長的 tuple 和 list 到底是什麼對象,還是無法得知。我們還得想點辦法追蹤下去。

如果不停增長的對象,是一些非通用的類型(例如你自己實現的一個 class),那麼問題就比較好定位了。

 

 

回到我的這個異常程式,為了找出 tuple 和 list 到底是什嗎? 我採用了排查的方式。由於程式的模組化還不錯,我可以每次禁用一個模組,然後重新跑程式,看看在這種情況下, tuple 和 list 是否仍然不停增長。這樣,很快就能將故障定位到具體的模組中。

 

最後終於找到了原因,屬於上面總結的第二種原因:

我的程式是一個多線程程式,多個線程作為生產者,一個線程作為消費者,通過非同步隊列通訊。由於消費者的處理速度跟不上生產者的速度,又沒有進行同步, 導致非同步隊列中的對象越來越多。

 

四、參考文檔

 

 

 

 

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.