为什么咸菜吃内存?(Why pickle eat memory?)

2019-07-05 06:14发布

我试图处理由小块腌写入数据到磁盘巨量。 下面是示例代码:

from cPickle import *
from gc import collect

PATH = r'd:\test.dat'
@profile
def func(item):
    for e in item:
        f = open(PATH, 'a', 0)
        f.write(dumps(e))
        f.flush()
        f.close()
        del f
        collect()

if __name__ == '__main__':
    k = [x for x in xrange(9999)]
    func(k)

打开()和close()置于其内循环,以排除在存储器中的数据累积的可能原因。

为了说明问题,我附上与Python 3D方模块获得内存分析的结果memory_profiler :

   Line #    Mem usage  Increment   Line Contents
==============================================
    14                           @profile
    15      9.02 MB    0.00 MB   def func(item):
    16      9.02 MB    0.00 MB       path= r'd:\test.dat'
    17
    18     10.88 MB    1.86 MB       for e in item:
    19     10.88 MB    0.00 MB           f = open(path, 'a', 0)
    20     10.88 MB    0.00 MB           f.write(dumps(e))
    21     10.88 MB    0.00 MB           f.flush()
    22     10.88 MB    0.00 MB           f.close()
    23     10.88 MB    0.00 MB           del f
    24                                   collect()

在循环期间发生奇怪的内存使用量的增长的执行。 它如何被淘汰? 有什么想法吗?

当输入数据的量增加这一额外的数据量可以长到规模大得多然后输入(UPD:在真正的任务,我得到300 + MB)

而更广泛的问题 - 这方面存在正确与Python中大的量IO数据的工作吗?

UPD:我重写了代码,只留下循环体的时候看到的增长情况而言,这里的结果:

Line #    Mem usage  Increment   Line Contents
==============================================
    14                           @profile
    15      9.00 MB    0.00 MB   def func(item):
    16      9.00 MB    0.00 MB       path= r'd:\test.dat'
    17
    18                               #for e in item:
    19      9.02 MB    0.02 MB       f = open(path, 'a', 0)
    20      9.23 MB    0.21 MB       d = dumps(item)
    21      9.23 MB    0.00 MB       f.write(d)
    22      9.23 MB    0.00 MB       f.flush()
    23      9.23 MB    0.00 MB       f.close()
    24      9.23 MB    0.00 MB       del f
    25      9.23 MB    0.00 MB       collect()

这似乎是转储()吃内存。 (虽然我真的以为这将是写())

Answer 1:

泡椒消耗大量的内存,请解释在这里: http://www.shocksolution.com/2010/01/storing-large-numpy-arrays-on-disk-python-pickle-vs-hdf5adsf/

为什么泡椒消耗这么多的内存? 其原因是,HDF是一个二进制数据管道,而味酸是一个对象序列化协议。 味酸实际上由该转化的对象为一系列的操作码,并将其写入到磁盘上的简单的虚拟机(VM)的。 要unpickle的东西,虚拟机读取并解释操作码和重建的对象。 这种方法的缺点是VM具有构造对象的完整副本在内存中写入到磁盘之前。

味酸,因为在大多数情况下,内存消耗也无所谓了很多非常适合小的用例或测试。

对于您必须转储和装载大量的文件和/或大文件,你应该考虑使用其他的方式来存储你的数据密集型工作(例如:HDF,写你自己的序列化/你的对象反序列化方法,...)



文章来源: Why pickle eat memory?