Python - 不同的对象创建方法 - 内存分配

时间:2014-04-19 01:45:37

标签: python-2.7 memory-management

我得到了关于de / serialization的earlier question的一个很好的答案,这使我创建了一个方法,可以从文件中反序列化defaultdict(list)(如果存在),或者创建字典本身文件不存在。

实施简单代码后

try:
    #deserialize - this takes about 6 seconds
    with open('dict.flat') as stream:
        for line in stream:
            vals = line.split()
            lexicon[vals[0]] = vals[1:]
except:
    #create new - this takes about 40 seconds
    for word in lexicon_file:
        word = word.lower()
            for letter n-gram in word:
                lexicon[n-gram].append(word)
    #serialize - about 6 seconds
    with open('dict.flat', 'w') as stream:
        stream.write('\n'.join([' '.join([k] + v) for k, v in lexicon.iteritems()]))

我对从文件反序列化时脚本占用的内存量感到有些震惊。

(lexicon_file包含大约620 000个单词,处理过的defaultdict(list)包含25 000个键,而每个键包含1到133 000个字符串的列表(平均500个,中位数20)。 每个键都是一个字母bi / trigram,它的值是包含关键字母n-gram的单词。)

当脚本重新创建词典时,整个过程不会使用超过160 MB的RAM - 序列化文件本身略高于129 MB。 当脚本反序列化词典时,python.exe占用的RAM量最多会跳到500 MB。

当我尝试使用

模拟在反序列化过程中创建新词典的方法时
#deserialize one by one - about 15 seconds
with open('dict.flat') as stream:
    for line in stream:
        vals = line.split()
        for item in vals[1:]:
            lexicon[vals[0]].append(item)

结果完全相同 - 除了此代码段运行速度明显变慢。

是什么导致内存消耗的这种巨大差异?我的第一个问题是,由于结果列表中的很多元素完全相同,因此python以某种方式使用引用更有效地创建字典 - 在反序列化和将整个列表映射到键时没有时间。但如果是这种情况,为什么这个问题没有通过逐个附加项来解决,就像创建一个新的词典一样?

编辑:this question已经讨论过这个话题了(我怎么错过了?!)。可以使用intern()函数强制Python从引用创建字典:

#deserialize with intern - 45 seconds
with open('dict.flat') as stream:
    for line in stream:
        vals = line.split()
        for item in vals[1:]:
            lexicon[intern(vals[0])].append(intern(item))

这减少了字典对预期值(160 MB)所占用的RAM量,但偏移量是计算时间恢复到与重新创建字典时相同的值,这完全否定了序列化的原因。

0 个答案:

没有答案