Python 如何深度获取包含内容的列表大小?
我很惊讶,sys.getsizeof( 10000*[x] )
的结果是 40036,无论 x 是 0、"a"、1000*"a" 还是 {}。
有没有一个 deep_getsizeof
能正确考虑共享内存的元素呢?
(这个问题是因为我在查看内存中的数据库表,比如 range(1000000) -> 省名:用列表还是字典?)
(我在一台运行 Python 2.6.4 的 mac ppc 上。)
补充说明:
10000*["Mississippi"] 实际上是 10000 个指向同一个 "Mississippi" 的指针,正如几个人指出的那样。试试这个:
nstates = [AlabamatoWyoming() for j in xrange(N)]
其中 AlabamatoWyoming() 会返回一个字符串 "Alabama" .. "Wyoming"。
那 deep_getsizeof(nstates) 是多少呢?
(我们怎么知道呢?)
- 一个合适的 deep_getsizeof:很难,大约需要垃圾回收跟踪器
- 从总虚拟内存中估算
- 对 Python 实现的内部知识
- 猜测。
补充 1月25日:
还可以查看 Python 什么时候为相同字符串分配新内存
5 个回答
如果你的列表里只放了长度相同的对象,你可以通过这样做来得到一个更准确的大小估计。
def getSize(array):
return sys.getsizeof(array) + len(array) * sys.getsizeof(array[0])
显然,这种方法对长度不一样的字符串效果就不好了。
如果你只是想在调试或者开发的时候计算大小,而不太在意性能的话,你可以递归地遍历所有项目,计算总大小。需要注意的是,这种方法不能正确处理多个地方引用同一个对象的情况。
10000 * [x] 会生成一个包含10000个相同对象的列表,所以它的大小其实比你想的要准确。不过,深度计算大小就很麻烦,因为你无法告诉Python什么时候停止计算。每个对象都有一个类型对象的引用。那这个类型对象要算吗?如果这个类型对象是最后一个引用,那么如果你删除了这个对象,类型对象也会消失,那该怎么办?如果列表里有多个(不同的)对象都指向同一个字符串对象,那这个字符串对象应该算一次,还是算多次呢?
总之,获取一个数据结构的大小是非常复杂的,而 sys.getsizeof() 本来就不应该被添加进来 :S
你可以看看 guppy/heapy;我自己没怎么使用过,但我的几个同事用它来分析内存,效果不错。
虽然说明书写得可以更好,但 这个教程 对基本概念的解释还算不错。