簡體   English   中英

Python 中 memory 泄漏的單元測試

[英]Unit test for memory leaks in Python

有沒有辦法對 Python 中的 memory 泄漏運行單元測試? 我已經編寫了一些 C++ 綁定代碼,並希望確保它不會泄漏 memory。

例如,我想要一個像下面這樣的測試:

memory_usage_0 = 0
memory_usage_1 = 0
memory_usage_0 = get_memory_usage()
do_cpp_bound_operation()
memory_usage_1 = get_memory_usage()
assert memory_usage_0 == memory_usage_1

如果您願意讓您的單元測試變慢,可以根據您的編碼示例嘗試以下方法:

將您的代碼片段更改為如下所示:

gc.collect()
callCppCoreGenerationFunction()
do_cpp_bound_operation()
gc.collect()
callCppCoreGenerationFunction()
compareCores()

Your callCppCoreGenerationFunction can call a c or C++ function that is as simple as forking a new process and having the child kill itself, for example, by having the child reference a null pointer. 這很簡單,因為您不希望這個 function 在內核生成期間通過額外的 python 分配來攪渾水。

這里要討論的關鍵部分是 compareCores()。 為此,您可以使用分叉進程的標准 python 代碼,因為您已經有要比較的內核,並且無需擔心結果失真。 例如,您可以創建一個 shell 腳本來計算您的答案。

所以現在的問題是 shell 腳本中的 go 應該是什么。 它應該做的第一件事是按創建順序列出內核,以便您可以比較兩個最近的內核。 然后在 chap 中打開每個內核(開源軟件可在https://github.com/vmware/chap獲得)。 對於每個核心,您應該在 chap 中打開它並在 chap 提示符下運行以下命令:

count leaked

這看起來像這樣,將捕獲泄漏的本機分配對象和一些(但絕對不是全部)泄漏的 python 對象。

chap> count leaked
0 allocations use 0x0 (0) bytes.

該特定命令非常可靠,因為 chap 旨在避免泄漏的誤報。 因此,您甚至可以只在兩個核心中的第二個上運行它,而這樣的檢查根本不需要第一個核心。 如果您確實發現泄漏是可以用來分析泄漏的其他 chap 命令,但如果您只想知道是否有此類泄漏,而不是為什么,那么計數就足夠了。

describe used

這將描述所有已分配但未釋放的分配(python 和本機)。 output 看起來像這樣,但有更多行:

Anchored allocation at 7f505b117630 of size 40
This allocation matches pattern ContainerPythonObject.
This has a PyGC_Head at the start so the real PyObject is at offset 0x10.
This has reference count 1 and python type 0x903f20 (dict)

Anchored allocation at 7f505b117670 of size 40
This allocation matches pattern ContainerPythonObject.
This has a PyGC_Head at the start so the real PyObject is at offset 0x10.
This has reference count 1 and python type 0x8fd660 (list)

Anchored allocation at 16f8a80 of size 238
This allocation matches pattern SimplePythonObject.
This has reference count 1 and python type 0x7f5e824cdfe0 (str)
This has a string of length 512 starting with
"bytearray(iterable_of_ints) -> bytearray
bytearray(string, encoding[, errors]".

In that output, a %SimplePythonObject" is some python object like a str that doesn't reference other python objects and a "%ContainerPythonObject" is a python object that can reference other python objects and so is subject to garbage collection.

請注意,給出了每個此類 object 的 python 引用計數。 這意味着,在回答您有關檢查 c++ 代碼是否錯誤地完成引用計數的問題時,這將反映在 Z78E6221F6393D1356681DB398F14CE6 文件中給定 object 的引用計數的變化中。 因此,可以通過這種方式捕獲小到會導致泄漏的單個引用計數錯誤。

%SimplePythonObject 通常可以被檢測為泄漏,只需對一個內核使用“泄漏計數”,只要沒有分配(python 或本機或...)仍然引用它,但使用比較“描述使用”的 output 是更通用,並為您的用例提供更好的覆蓋范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM