python tracemalloc 模块分配统计何时与 ps 或 pmap 中显示的不匹配?

Rya*_*heu 6 python memory-management cython

我正在尝试追踪内存泄漏,所以我已经完成了

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)
Run Code Online (Sandbox Code Playgroud)

这显示没有主要分配,所有内存分配都非常小,而我看到在psand 中分配了 8+ GB 内存pmap(在运行命令之前和之后以及运行垃圾收集之后进行检查)。此外,tracemalloc.get_traced_memory确认tracemalloc没有看到很多分配。pympler也没有看到分配。

有谁知道什么时候会出现这种情况?某些模块正在使用 cython,这会导致 tracemalloc 出现问题吗?

在 pmap 中,分配看起来像:

0000000002183000 6492008 6491876 6491876 rw--- [ anon ]

dan*_*nny 9

从关于tracemalloc的文档:

The tracemalloc module is a debug tool to trace memory blocks allocated by Python.

换句话说,tracemalloc 看不到 python 解释器未分配的内存。这将包括PyMalloc在 C-API 级别未完成的任何事情,包括malloc通过扩展使用的本机代码或malloc直接使用的扩展代码的所有标准 libc调用。

如果没有可重现的代码,就无法确定是否是这种情况。您可以尝试在 python 之外运行本机代码部分,例如通过 valgrind 来检测本机代码中的内存泄漏。

如果有 cython 代码在执行malloc,则可以切换到PyMalloc它以进行跟踪。


ead*_*ead 5

对@danny 的答案的补充,因为评论太长了。

如PEP-464中所述,使用PEP-445tracemalloc中引入的功能来跟踪内存分配。

通常,必须使用PyMem_RawMalloc而不是malloc为了能够用于tracemallocC 扩展。然而,由于相当长一段时间也使用pymem.h中的PyTraceMalloc_Track和作为补充(而不是用 替换它)。PyTraceMalloc_UntrackmallocPyMem_RawMalloc

例如,这就是 numpy 中使用的内容,因为为了能够包装原始 c 指针并接管其所有权,使用 numpymalloc而不是 python 分配器,后者针对小对象进行了优化 - 这不是最关键的场景numpy,如下所示:

/*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;
}
Run Code Online (Sandbox Code Playgroud)

因此,基本上,C 扩展有责任向tracemalloc模块报告内存分配,另一方面,tracemalloc不能真正信任其注册所有内存分配。