python 記憶體洩露的診斷
對於一個用 python 實現的,長期執行的後臺服務程式來說,如果記憶體持續增長,那麼很可能是有了“記憶體洩露”。
最近在我的專案中,就出現了記憶體持續增長的情況,goolge 了一下,發現 [url=http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks]Tracing Python memory leaks[/url] 講了一種診斷方式,並給出了例項。而我的案例與此文稍有不同,下面就結合我的案例,談談如何診斷記憶體洩露:
一、記憶體洩露的原因
對於 python 這種支援垃圾回收的語言來說,怎麼還會有記憶體洩露? 概括來說,有以下三種原因:
1、 所用到的用 C 語言開發的底層模組中出現了記憶體洩露。
2、 程式碼中用到了全域性的 list、 dict 或其它容器,不停的往這些容器中插入物件,而忘記了在使用完之後進行刪除回收
3、 程式碼中有“引用迴圈”, python 垃圾處理機制無法進行回收
二、 記憶體洩露的診斷思路
無論是哪種方式的記憶體洩露,最終表現的形式都是某些 python 物件在不停的增長;因此,首先是要找到這些異常的物件。
三、 記憶體洩露的診斷步驟
用到的工具: gc 模組和 [url=http://mg.pov.lt/objgraph.py]objgraph[/url] 模組
objgraph 是一個用於診斷記憶體問題的有用的工具
1、 在服務程式的迴圈邏輯中,選擇出一個診斷點
2、 在診斷點,插入如下診斷語句
3、 檢查統計資訊,找到異常物件。
執行加入診斷語句的服務程式,並將列印到螢幕上的統計資訊重定向到日誌中。
執行一段時間後,就可以來分析日誌,看看哪些物件在不停的增長。
以我的程式為例,我將日誌記錄到 log.txt 中,執行一段時間後,發現 tuple 和 list 型別的物件不停增長:
如果不停增長的物件,是一些非通用的型別(例如你自己實現的一個 class),那麼問題就比較好定位,例如 [url=http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks]Tracing Python memory leaks[/url]中提到的案例。
而對 tuple 和 list 這類通用型別,要想知道物件到底是什麼,洩露發生在哪裡,還得想點辦法。我採用了排查的方式。由於程式的模組化還不錯,可以每次禁用一個模組,然後重新跑程式,重新檢查日誌,看看 tuple 和 list 是否仍然不停增長。這樣,很快就能將故障定位到具體的模組中。
最後終於找到了原因,屬於上面總結的第二種原因:
我的程式是一個多執行緒程式,多個執行緒作為生產者,一個執行緒作為消費者,通過將一個 tuple 物件送入非同步佇列進行通訊。由於消費者的處理速度跟不上生產者的速度,又沒有進行同步, 導致非同步佇列中的物件越來越多。
四、參考文件
1. [url]http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks[/url]
2. [url]http://mg.pov.lt/blog/python-object-graphs.html[/url]
3. [url]http://mg.pov.lt/blog/hunting-python-memleaks[/url]
最近在我的專案中,就出現了記憶體持續增長的情況,goolge 了一下,發現 [url=http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks]Tracing Python memory leaks[/url] 講了一種診斷方式,並給出了例項。而我的案例與此文稍有不同,下面就結合我的案例,談談如何診斷記憶體洩露:
一、記憶體洩露的原因
對於 python 這種支援垃圾回收的語言來說,怎麼還會有記憶體洩露? 概括來說,有以下三種原因:
1、 所用到的用 C 語言開發的底層模組中出現了記憶體洩露。
2、 程式碼中用到了全域性的 list、 dict 或其它容器,不停的往這些容器中插入物件,而忘記了在使用完之後進行刪除回收
3、 程式碼中有“引用迴圈”, python 垃圾處理機制無法進行回收
二、 記憶體洩露的診斷思路
無論是哪種方式的記憶體洩露,最終表現的形式都是某些 python 物件在不停的增長;因此,首先是要找到這些異常的物件。
三、 記憶體洩露的診斷步驟
用到的工具: gc 模組和 [url=http://mg.pov.lt/objgraph.py]objgraph[/url] 模組
objgraph 是一個用於診斷記憶體問題的有用的工具
1、 在服務程式的迴圈邏輯中,選擇出一個診斷點
2、 在診斷點,插入如下診斷語句
import gc
import objgraph
### 強制進行垃圾回收
gc.collect()
### 列印出物件數目最多的 50 個型別資訊
objgraph.show_most_common_types(limit=50)
3、 檢查統計資訊,找到異常物件。
執行加入診斷語句的服務程式,並將列印到螢幕上的統計資訊重定向到日誌中。
執行一段時間後,就可以來分析日誌,看看哪些物件在不停的增長。
以我的程式為例,我將日誌記錄到 log.txt 中,執行一段時間後,發現 tuple 和 list 型別的物件不停增長:
# grep "^list " log.txt
# grep "^tuple " log.txt
如果不停增長的物件,是一些非通用的型別(例如你自己實現的一個 class),那麼問題就比較好定位,例如 [url=http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks]Tracing Python memory leaks[/url]中提到的案例。
而對 tuple 和 list 這類通用型別,要想知道物件到底是什麼,洩露發生在哪裡,還得想點辦法。我採用了排查的方式。由於程式的模組化還不錯,可以每次禁用一個模組,然後重新跑程式,重新檢查日誌,看看 tuple 和 list 是否仍然不停增長。這樣,很快就能將故障定位到具體的模組中。
最後終於找到了原因,屬於上面總結的第二種原因:
我的程式是一個多執行緒程式,多個執行緒作為生產者,一個執行緒作為消費者,通過將一個 tuple 物件送入非同步佇列進行通訊。由於消費者的處理速度跟不上生產者的速度,又沒有進行同步, 導致非同步佇列中的物件越來越多。
四、參考文件
1. [url]http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks[/url]
2. [url]http://mg.pov.lt/blog/python-object-graphs.html[/url]
3. [url]http://mg.pov.lt/blog/hunting-python-memleaks[/url]
相關文章
- Python實現記憶體洩露排查的示例Python記憶體洩露
- SHBrowseForFolder 記憶體洩露記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- ArkTS 的記憶體快照與記憶體洩露除錯記憶體洩露除錯
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- android Handler導致的記憶體洩露Android記憶體洩露
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- 簡單的記憶體“洩露”和“溢位”記憶體
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- win10驅動記憶體洩露如何解決_win10記憶體洩露處理方法Win10記憶體洩露
- Spark效能優化:診斷記憶體的消耗Spark優化記憶體
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- 乾貨分享:淺談記憶體洩露記憶體洩露
- 解決git記憶體洩露問題Git記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- 線上記憶體洩露定位--memleak工具記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- 記一次"記憶體洩露"排查過程記憶體洩露
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- C程式記憶體洩露檢測工具——ValgrindC程式記憶體洩露
- Android效能最佳化之記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- 案例:隱秘而低調的記憶體洩露(OOM)記憶體洩露OOM
- 經驗之談:記憶體洩露的原因以及分析記憶體洩露
- 記一次 .NET 某工控軟體 記憶體洩露分析記憶體洩露
- ThreadLocal原始碼解讀和記憶體洩露分析thread原始碼記憶體洩露
- 使用mtrace追蹤JVM堆外記憶體洩露JVM記憶體洩露
- 一次Kafka記憶體洩露排查經過Kafka記憶體洩露
- 前端面試題51----JS記憶體洩露前端面試題JS記憶體洩露
- 利用dotnet-dump分析docker容器記憶體洩露Docker記憶體洩露
- Android中使用Handler造成記憶體洩露的分析和解決Android記憶體洩露
- php常駐程式記憶體洩露的簡單解決PHP記憶體洩露
- [翻譯]查詢Windows記憶體洩露的幾種方法Windows記憶體洩露