muppy:获取按大小排序的 Python 程序中最大的 PyObject 的名称

muppy: Getting the name of the biggest PyObjects in a Python program sorted by size

我的程序存在内存泄漏问题。我正在使用 pympler 库中的 muppy 来打印程序中最大的 PyObjects 列表,这些列表按字节大小排序。这是一个如何使用它的可重现示例:

$pip install pympler

import numpy as np
from pympler import muppy, summary

foo = np.random.normal(size=(1000, 1000))
all_objects = muppy.get_objects()
sum1 = summary.summarize(all_objects)
summary.print_(sum1)

所以,我得到了这个结果:

                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          42 |      7.63 MB
                         str |       20870 |      3.40 MB
                        dict |        4538 |      2.19 MB
                        list |        4415 |      1.37 MB
                        code |        5882 |    830.05 KB
                        type |         969 |    775.52 KB
                       tuple |        3821 |    278.77 KB
          wrapper_descriptor |        2189 |    188.12 KB
                         set |         148 |    115.53 KB
  builtin_function_or_method |        1442 |    112.66 KB
           method_descriptor |        1406 |    109.84 KB
                     weakref |        1273 |    109.40 KB
                 abc.ABCMeta |          96 |     94.62 KB
                         int |        2769 |     81.01 KB
           getset_descriptor |         974 |     76.09 KB

但是这个结果按类型聚合了对象。所以,现在我知道某些数组或数组导致内存泄漏,但我不知道它们中的哪一个是问题的根源。我想得到一个类似的列表,但有明确的名称,比方说,前 15 个最大的对象。

我已经为一个最大的物体试过了:

sorted_objs = muppy.sort(all_objects)
print(sorted_objs[-1])
print(asizeof.asizeof(sorted_objs[-1]))

这实际上打印了 PyObject 和以字节为单位的大小。但是我也可以得到它的名字吗?即本例中的 "foo"。谢谢

我找不到使用这些库获取 pympler/muppy 返回的最大对象名称的解决方案。然而事实证明,您可以使用 objgraph 获取与解决内存泄漏相关的所有信息,包括变量名称和对象引用。

以下是如何继续的说明:

  1. 获取objgraph,例如用pip:

    pip3 install objgraph
    
  2. 绘制三个最大对象的参考图

    biggest_vars = muppy.sort(muppy.get_objects())[-3:]
    objgraph.show_backrefs(biggest_vars, filename='backref.png')
    

下面是一个示例,其中内存泄漏是由于 numpy 零数组在另一个线程中实例化并被两个名为 newsoundaudio_data 的变量引用。不知何故,当线程完成时,这些零数组没有被删除。