python tracemalloc 模块分配统计数据何时会与 ps 或 pmap 中显示的不匹配?
When would the python tracemalloc module allocations statistics not match what's shown in ps or pmap?
我正在尝试追踪内存泄漏,所以我已经完成了
import tracemalloc
tracemalloc.start()
<function call>
# copy pasted this from documentation
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)
这表明没有主要分配,所有内存分配都非常小,而我看到在 ps
和 pmap
中分配了 8+ GB 内存(检查 运行 之前和之后命令,以及 运行 垃圾回收之后)。此外,tracemalloc.get_traced_memory
确认 tracemalloc
没有看到很多分配。 pympler
也没有看到分配。
有谁知道什么时候会出现这种情况?一些模块正在使用 cython,这会导致 tracemalloc 出现问题吗?
在 pmap 中,分配如下所示:
0000000002183000 6492008 6491876 6491876 rw--- [ anon ]
来自 tracemalloc 上的文档:
The tracemalloc module is a debug tool to trace memory blocks allocated by Python.
换句话说,tracemalloc 看不到未由 python 解释器分配的内存。这将包括 PyMalloc
在 C-API 级别未完成的任何事情,包括通过扩展使用的本机代码或直接使用 malloc
的扩展代码的所有标准 libc malloc
调用.
如果没有代码重现,就无法确定这里是否是这种情况。您可以尝试 运行 python 之外的本机代码部分,例如通过 valgrind 来检测本机代码中的内存泄漏。
如果有 cython 代码在做 malloc
,可以切换到 PyMalloc
来跟踪它。
@danny 的回答的补充,因为评论太长了。
如 PEP-464, tracemalloc
uses functionality introduced in PEP-445 中所述,用于跟踪内存分配。
通常,人们必须使用 PyMem_RawMalloc
instead of malloc
in order to be able to use tracemalloc
for a C-extension. However, since quite some time also using PyTraceMalloc_Track
and PyTraceMalloc_Untrack
from pymem.h 作为 malloc
的补充(而不是用 PyMem_RawMalloc
代替)。
这就是在 numpy 中使用的示例,因为为了能够包装原始 c 指针并接管其所有权,numpy 使用了 malloc
而不是 python-allocator ,它针对小对象进行了优化 - 不是 numpy 最关键的场景,可以看出 here:
/*NUMPY_API
* Allocates memory for array data.
*/
NPY_NO_EXPORT void *
PyDataMem_NEW(size_t size)
{
void *result;
result = malloc(size);
if (_PyDataMem_eventhook != NULL) {
NPY_ALLOW_C_API_DEF
NPY_ALLOW_C_API
if (_PyDataMem_eventhook != NULL) {
(*_PyDataMem_eventhook)(NULL, result, size,
_PyDataMem_eventhook_user_data);
}
NPY_DISABLE_C_API
}
PyTraceMalloc_Track(NPY_TRACE_DOMAIN, (npy_uintp)result, size);
return result;
}
所以基本上,C 扩展有责任向 tracemalloc
模块报告内存分配,另一方面,tracemalloc
不能真正信任注册所有内存分配。
我正在尝试追踪内存泄漏,所以我已经完成了
import tracemalloc
tracemalloc.start()
<function call>
# copy pasted this from documentation
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)
这表明没有主要分配,所有内存分配都非常小,而我看到在 ps
和 pmap
中分配了 8+ GB 内存(检查 运行 之前和之后命令,以及 运行 垃圾回收之后)。此外,tracemalloc.get_traced_memory
确认 tracemalloc
没有看到很多分配。 pympler
也没有看到分配。
有谁知道什么时候会出现这种情况?一些模块正在使用 cython,这会导致 tracemalloc 出现问题吗?
在 pmap 中,分配如下所示:
0000000002183000 6492008 6491876 6491876 rw--- [ anon ]
来自 tracemalloc 上的文档:
The tracemalloc module is a debug tool to trace memory blocks allocated by Python.
换句话说,tracemalloc 看不到未由 python 解释器分配的内存。这将包括 PyMalloc
在 C-API 级别未完成的任何事情,包括通过扩展使用的本机代码或直接使用 malloc
的扩展代码的所有标准 libc malloc
调用.
如果没有代码重现,就无法确定这里是否是这种情况。您可以尝试 运行 python 之外的本机代码部分,例如通过 valgrind 来检测本机代码中的内存泄漏。
如果有 cython 代码在做 malloc
,可以切换到 PyMalloc
来跟踪它。
@danny 的回答的补充,因为评论太长了。
如 PEP-464, tracemalloc
uses functionality introduced in PEP-445 中所述,用于跟踪内存分配。
通常,人们必须使用 PyMem_RawMalloc
instead of malloc
in order to be able to use tracemalloc
for a C-extension. However, since quite some time also using PyTraceMalloc_Track
and PyTraceMalloc_Untrack
from pymem.h 作为 malloc
的补充(而不是用 PyMem_RawMalloc
代替)。
这就是在 numpy 中使用的示例,因为为了能够包装原始 c 指针并接管其所有权,numpy 使用了 malloc
而不是 python-allocator ,它针对小对象进行了优化 - 不是 numpy 最关键的场景,可以看出 here:
/*NUMPY_API
* Allocates memory for array data.
*/
NPY_NO_EXPORT void *
PyDataMem_NEW(size_t size)
{
void *result;
result = malloc(size);
if (_PyDataMem_eventhook != NULL) {
NPY_ALLOW_C_API_DEF
NPY_ALLOW_C_API
if (_PyDataMem_eventhook != NULL) {
(*_PyDataMem_eventhook)(NULL, result, size,
_PyDataMem_eventhook_user_data);
}
NPY_DISABLE_C_API
}
PyTraceMalloc_Track(NPY_TRACE_DOMAIN, (npy_uintp)result, size);
return result;
}
所以基本上,C 扩展有责任向 tracemalloc
模块报告内存分配,另一方面,tracemalloc
不能真正信任注册所有内存分配。