【问题标题】:Who ate my Python memory? [duplicate]谁吃了我的 Python 内存? [复制]
【发布时间】:2014-05-03 20:52:13
【问题描述】:

关于 Python 代码的一般问题。 我如何才能最有效地定位我的 Python 代码在内存使用方面最糟糕的部分?

参见例如这个小例子

def my_func():
    a = [1] * (12 ** 4)
    return a

def my_func2():
    b = [2] * (10 ** 7)
    return b

if __name__ == '__main__':
    a1 = my_func()
    a2 = my_func2()

如何自动判断 a2 的大小比 a1 大得多? 我怎样才能 - 仍然是自动化的 - 将其根植于 my_func1()my_func2()

对于 C/C++ 代码,我会使用 valgrind --tool=massif,它可以直接定位有关内存使用的重量级 - 但对于 Python,我需要你的帮助。 Meliae 似乎给出了一些答案,但不如 massif 对 C/C++ 所做的那样好。

【问题讨论】:

  • 推荐的python分析器here

标签: python profiling


【解决方案1】:

locals() (resp.globals()) 返回一个包含所有本地(resp.global)活动对象的字典。你可以像这样使用它们:

import sys
sizes = dict((obj, sys.getsizeof(eval(obj))) for obj in locals().keys())

缺点是它不会意识到尚未完全实现__getsizeof__ 的对象,例如 Numpy 数组或引用。例如,如果你这样做:

print sys.getsizeof(a2)
sys.getsizeof(a1)
a2.append(a1)
print sys.getsizeof(a2)

输出将是:

40000036
   82980
45000064   ---> The list is 60 times bigger!

当然,仅仅删除 a1 并不会释放它的 82 k,因为在 a1 中还有一个引用。但我们可以让它变得更奇怪:

a2 = my_func2()
print sys.getsizeof(a2)
a2.append(a2)
print sys.getsizeof(a2)

而且输出看起来会非常熟悉:

40000036
45000064

其他工具可能会对此实施解决方法,并搜索引用树,但 Python 中完整内存分析的一般问题仍未解决。当对象通过 C API 在引用计数器范围之外存储数据时,情况会变得更糟,例如发生在 Numpy 数组中。

也就是说,对于大多数实际情况,有些工具“足够好”。正如在引用的链接中,Heapy 是一个非常好的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    相关资源
    最近更新 更多