Gil*_*tes 12 python performance file-io pickle persistent
我试图处理通过小块将大量的腌制数据写入磁盘.这是示例代码:
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)
Run Code Online (Sandbox Code Playgroud)
内置循环中的open()和close()可以排除内存中数据累积的可能原因.
为了说明问题,我附上了使用Python 3d party模块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()
Run Code Online (Sandbox Code Playgroud)
在执行循环期间,发生奇怪的内存使用增长.如何消除它?有什么想法吗?
当输入数据量增加时,此附加数据的数量可以增大到大于输入的大小(更新:在实际任务中我获得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()
Run Code Online (Sandbox Code Playgroud)
似乎dumps()吃掉了内存.(虽然我实际上认为它会写())
小智 10
Pickle消耗大量RAM,请参见此处的解释:http://www.shocksolution.com/2010/01/storing-large-numpy-arrays-on-disk-python-pickle-vs-hdf5adsf/
为什么Pickle会消耗更多的内存?原因是HDF是二进制数据管道,而Pickle是一个对象序列化协议.Pickle实际上由一个简单的虚拟机(VM)组成,它将一个对象转换为一系列操作码并将它们写入磁盘.为了解开某些东西,VM读取并解释操作码并重建对象.这种方法的缺点是VM必须在将对象写入磁盘之前在内存中构造对象的完整副本.
Pickle非常适合小型用例或测试,因为在大多数情况下,内存消耗并不重要.
对于必须转储和加载大量文件和/或大文件的密集型工作,您应该考虑使用另一种方式来存储数据(例如:hdf,为您的对象编写自己的序列化/反序列化方法,...)
| 归档时间: |
|
| 查看次数: |
4799 次 |
| 最近记录: |