jul*_*ria 18 python performance serialization
我正在实现一个需要序列化和反序列化大对象的程序,所以我正在进行一些测试pickle,cPickle并marshal选择模块来选择最佳模块.一路上我发现了一些非常有趣的东西:
我正在使用dumps然后loads(对于每个模块)列表中的dicts,元组,整数,浮点数和字符串.
这是我的基准测试的输出:
DUMPING a list of length 7340032
----------------------------------------------------------------------
pickle => 14.675 seconds
length of pickle serialized string: 31457430
cPickle => 2.619 seconds
length of cPickle serialized string: 31457457
marshal => 0.991 seconds
length of marshal serialized string: 117440540
LOADING a list of length: 7340032
----------------------------------------------------------------------
pickle => 13.768 seconds
(same length?) 7340032 == 7340032
cPickle => 2.038 seconds
(same length?) 7340032 == 7340032
marshal => 6.378 seconds
(same length?) 7340032 == 7340032
Run Code Online (Sandbox Code Playgroud)
因此,根据这些结果,我们可以看到在基准测试marshal的倾销部分中速度非常快:
快于14.8倍,比
pickle快2.6倍cPickle.
但是,对于我很大的惊喜,marshal是迄今为止速度低于cPickle在装载部分:
比它快2.2倍
pickle,但比它快3.1倍cPickle.
至于RAM,加载时的marshal性能也非常低效:

我猜测加载的marshal速度如此之慢的原因与它的序列化字符串的长度(比pickle和更长cPickle)有某种关系.
marshal转储更快,加载更慢?marshal序列化的字符串太长了?marshal在RAM中加载效率太低?marshal装载性能?marshal快速转储与cPickle快速加载合并?Joh*_*lin 19
cPickle有一个更聪明的算法,marshal并且能够做一些技巧来减少大对象使用的空间.这意味着解码速度会慢,但编码速度会更快,因为结果输出更小.
marshal是简单的,并且直接将对象序列化,而不进行任何进一步的分析.这也解释了为什么marshal加载效率非常低,它只需要做更多的工作 - 就像从磁盘读取更多数据一样 - 能够做同样的事情cPickle.
marshal而cPickle到底是真的不同的东西,你不能真正得到既快又省电和快速加载,因为快速保存意味着分析数据结构更少,这意味着节约了大量的数据到磁盘.
关于marshal可能与其他Python版本不兼容的事实,您通常应该使用cPickle:
"这不是一般的"持久性"模块.对于通过RPC调用的Python对象的一般持久性和传递,请参阅pickle和shelve模块.Machehal模块主要用于支持读取和编写Python模块的"伪编译"代码.pyc文件.因此,Python维护者保留在需要时以向后不兼容的方式修改编组格式的权利.如果您要对Python对象进行序列化和反序列化,请使用pickle模块 - 性能可比,版本独立性得到保证,而pickle支持的范围远远超过了元帅." (关于元帅的python文档)
小智 13
有些人可能认为这太过分了,但是我通过简单地使用gc.disable()和gc.enable()包装pickle转储调用取得了很大的成功.例如,下面写一个~50MB字典列表的剪辑从78秒到4.
# not a complete example....
gc.disable()
cPickle.dump(params,fout,cPickle.HIGHEST_PROTOCOL)
fout.close()
gc.enable()
Run Code Online (Sandbox Code Playgroud)
这些基准测试之间的区别为加速cPickle提供了一个想法:
Input: ["This is a string of 33 characters" for _ in xrange(1000000)]
cPickle dumps 0.199 s loads 0.099 s 2002041 bytes
marshal dumps 0.368 s loads 0.138 s 38000005 bytes
Input: ["This is a string of 33 "+"characters" for _ in xrange(1000000)]
cPickle dumps 1.374 s loads 0.550 s 40001244 bytes
marshal dumps 0.361 s loads 0.141 s 38000005 bytes
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,列表重复相同的字符串.第二个列表是等效的,但每个字符串都是一个单独的对象,因为它是表达式的结果.现在,如果您最初是从外部源读取数据,则可以考虑使用某种字符串重复数据删除.
你可以制作cPickle cca.通过创建cPickle.Pickler实例然后将未记录的选项'fast'设置为1,可以更快50倍(!):
outfile = open('outfile.pickle')
fastPickler = cPickle.Pickler(outfile, cPickle.HIGHEST_PROTOCOL)
fastPickler.fast = 1
fastPickler.dump(myHugeObject)
outfile.close()
Run Code Online (Sandbox Code Playgroud)
但是如果你的myHugeObject有循环引用,dump方法永远不会结束.
| 归档时间: |
|
| 查看次数: |
10333 次 |
| 最近记录: |