我有一个关于Python简单链表及其内存消耗的问题。
以下是代码:
import sys
class Record:
def __init__(self,elem):
self.elem=elem
self.next=None
def size(self):
print 'elem.size = ', sys.getsizeof(self.elem)
print 'next.size = ', sys.getsizeof(self.next)
class LinkedList:
def __init__(self):
self.first=None
self.last=None
def addAsLast(self,elem):
rec=Record(elem)
if self.first==None:
self.first=self.last=rec
else:
self.last.next=rec
self.last=rec
if __name__=="__main__":
l=LinkedList()
r = Record(1)
r.size()
maxx = 10000000
r = range(1, maxx)
print 'size of r: ', sys.getsizeof(r)
print 'size of r[n-1]: ', sys.getsizeof(r[maxx-2])
for i in r:
if(i% (maxx/10) == 0): print '.'
l.addAsLast(i)
print "The End"
我的问题是:运行这个脚本会消耗1.7 GB的内存。
输出如下:
elem.size = 12
next.size = 8
size of r: 40000028
size of r[n-1]: 12
那么,让我们进行一些快速的数学计算:
1000万个记录。
每个记录有12个字节(元素)+ 8个字节(指向下一个记录的指针)= 20字节
20字节 * 1000万 = 2亿字节 = 190.7 MB
即使我必须考虑由range()函数分配的列表(约30 MB),我如何管理这样巨大的内存消耗?我在这段代码中犯了什么愚蠢的错误吗?我希望答案会让我感到惭愧和抱歉,但是到目前为止,我只是在想究竟发生了什么!
非常感谢您的帮助。
Record
类的size
方法,并将其打印为sys.sizeof(self)
而不是两个组件元素。它是32字节,而不是20字节,因为类结构中有开销。 - Aaron Drecpool=[None]*10000000; ... rec=recpool[j]; j+=1
这样的方法,然后看看会发生什么。 - Elazargc.disable()
。 - Elazar__slots__
,你将会严重减少数据结构的大小,因为__dict__
将被消除。此外,链表是一种非常浪费内存的结构,除非你的有效载荷很大。除非你需要从一个非常长的列表中快速删除,否则请避免使用它,即使这样也要考虑跳表等其他结构。 - 9000