首頁 > 軟體

Python實現記憶體洩露排查的範例詳解

2023-01-22 14:00:19

一般情況下只有需要長期執行的專案才會去關注記憶體的增長情況,即使是很小部分的記憶體洩露經過長期的執行仍然會產生很大的隱患。

python本身也是支援垃圾的自動回收的,但是在特定的情況下也是會出現記憶體洩露的問題的。

比如對於很多全域性的列表(list)/字典(dict)等物件在經過不斷的資料賦值而沒有進行手動回收,或者某些物件被不停的迴圈參照而不能及時的進行回收等都會產生記憶體洩露的情況。

一般在python程式碼塊的偵錯過程中會使用memory-profiler、filprofiler、objgraph等三種方式進行輔助分析,今天這裡主要介紹使用objgraph物件提供的函數介面來進行記憶體洩露的分析。

objgraph是python的非標準模組,因此需要使用pip的方式安裝一下。

pip install objgraph

更多詳細的介紹可以存取下面的官方地址進行檢視。

https://mg.pov.lt/objgraph/

接下來就可以直接將objgraph匯入到我們的程式碼塊中進行使用了。

# Importing the objgraph module and renaming it to graph.
import objgraph as graph

這裡初始化一組字典型別的資料物件。

dict_ = {
    '姓名': ['Python', 'Java', 'Scala'],
    '年齡': ['21', '22', '19']
}

通過objgraph.count()函數,可以統計出GC中的dict_物件的數目是多少。

# Counting the number of dict_ objects in the GC.
print(graph.count(dict_))

和objgraph.count()函數對應的是可以使用by_type返回該物件在GC中的列表,若是GC返回的為空的列表說明已經被回收了。

# Returning a list of dict_ objects in the GC.
print(graph.by_type(dict_))

在統計記憶體洩露時比較好用的函數就是graph.show_growth()函數,可以統計自上次呼叫以來增加得最多的物件。

# Showing the growth of objects in the memory since the last time it was called.
print(graph.show_growth())

# function                       3013     +3013
# tuple                          1463     +1463
# dict                           1417     +1417
# wrapper_descriptor             1178     +1178
# ReferenceType                   883      +883
# method_descriptor               814      +814
# builtin_function_or_method      794      +794
# getset_descriptor               514      +514
# type                            463      +463
# list                            436      +436
# None

可以根據返回結果中的物件每次增加的數量來判斷記憶體洩露的相關情況。

還有一個比較常用的分析函數就是graph.show_most_common_types(),可以按照從大到小的方式列出物件範例比較多的情況。

# Showing the most common types of objects in the memory.
print(graph.show_most_common_types())

# function                   3013
# tuple                      1463
# dict                       1417
# wrapper_descriptor         1178
# ReferenceType              883
# method_descriptor          814
# builtin_function_or_method 794
# getset_descriptor          514
# type                       463
# list                       436
# None

最後一個比較使用函數就是show_backrefs函數,使用它可以分析出記憶體洩露的原因是什麼。

它會生成一張有關objs的參照圖,可以看出物件為什麼不釋放?只是呼叫該函數時的引數比較多,下面是該函數的介面。

# def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
#                   highlight=None, filename=None, extra_info=None,
#                   refcounts=False, shortnames=True, output=None,
#                   extra_node_attrs=None):

我們還是和上面一樣使用dict_作為物件進行分析。

# Showing the back references of the dict_ object.
graph.show_backrefs(dict_)

執行完成後dot型別的圖片已經生成了,發現出現了下面的錯誤,意思是沒有發現支援dot的影象元件。

# Graph written to C:Users86159AppDataLocalTempobjgraph-dkqm85f0.dot (4 nodes)
# Graph viewer (xdot) and image renderer (dot) not found, not doing anything else

可以使用pip的方式分別安裝graphviz xdot,這兩個python的非標準模組。

pip install graphviz xdot

若是檢視.dot決策樹影象可以使用graphviz工具,可以到下面地址進行下載安裝。

https://graphviz.org/download/

安裝完成後設定環境變數,然後重啟開發工具(這裡使用的是pycharm)即可。

到此這篇關於Python實現記憶體洩露排查的範例詳解的文章就介紹到這了,更多相關Python記憶體洩露排查內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com