5

我对 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 的 RAM

输出是:

elem.size =  12 
next.size =  8 
size of r:  40000028
size of r[n-1]:  12

所以,让我们做一些快速的数学运算:

1000 万条记录。

每个记录有 12 个字节(elem)+ 8 个字节(指向下一个的指针)= 20 个字节

20 字节 * 1000 万 = 200.000.000 字节 = 190.7 MB

即使我必须考虑 range() 函数分配的列表(大约 30 MB),我该如何管理内存消耗的巨大差距?我在这段代码中犯了一些愚蠢的错误吗?我希望答案会让我感到羞耻和抱歉,但据我所知,我只是想知道发生了什么!

在此先感谢您的帮助。

4

2 回答 2

0
>>> class Record:
...     def __init__(self, elem):
...             self.elem = elem
...             self.next = None   
... 
>>> r = Record(1)
>>> sys.getsizeof(r)
72

还是我错过了什么?

另外,在我的系统上:

>>> sys.getsizeof(1)
24
>>> sys.getsizeof(None)
16
于 2013-06-05T22:58:35.197 回答
0

修改后的打印输出如下:

class Record:
    def __init__(self,elem):
        self.elem=elem
        self.next=None

    def size(self):
        print 'Record size = ', sys.getsizeof(self)
        print 'elem.size = ', sys.getsizeof(self.elem)
        print 'next.size = ', sys.getsizeof(self.next)

输出 :

Record size =  72
elem.size =  24
next.size =  16

所以,我的每个链表节点都是 72 字节 x 10M 应该是 720MB,.72GB

我运行程序,使用top,发现内存开销为3.6G。我的 elem 大小是你的两倍,我注意到你消耗的总内存是你的两倍(3.6G,而 1.7G)。

这一定是由于额外的 python 内存开销,例如垃圾收集。

于 2013-09-16T22:11:43.027 回答