首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >马歇尔转储更快,cPickle装载更快

马歇尔转储更快,cPickle装载更快
EN

Stack Overflow用户
提问于 2011-12-15 01:28:39
回答 6查看 12.8K关注 0票数 19

我正在实现一个需要序列化和反序列化大型对象的程序,所以我使用picklecPicklemarshal模块进行了一些测试,以选择最佳的模块。一路走来,我发现了一件非常有趣的事情:

我使用的是dumps,然后是loads (对于每个模块),它们都是在一个数据库、元组、ints、浮点数和字符串列表中使用的。

这是我基准的输出:

代码语言:javascript
复制
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

因此,从这些结果中我们可以看到,marshal在基准测试的倾卸部分中非常快:

pickle快14.8倍,比cPickle快2.6倍。

但是,令我惊讶的是,marshal than 部分比cPickle慢得多:

pickle快2.2倍,比cPickle慢3.1倍。

至于内存,marshal性能在加载时也非常低效:

我猜想使用marshal加载如此缓慢的原因与其序列化字符串的长度有关(比picklecPickle长得多)。

  • 为什么marshal转储速度更快,加载速度更慢?
  • 为什么marshal序列化字符串这么长?
  • 为什么marshal在内存中的加载效率这么低?
  • 有办法提高marshal的加载性能吗?
  • 有办法将marshal快速转储与cPickle快速加载合并吗?
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-12-18 13:49:39

cPickle有一个比marshal更聪明的算法,并且能够做一些技巧来减少大型对象所使用的空间。这意味着解码速度较慢,但编码速度较快,因为结果输出较小。marshal是简单化的,它将对象直接序列化为- is,而不做任何进一步的分析。这也解释了为什么marshal加载效率如此之低,它只需做更多的工作--比如从磁盘读取更多的数据--才能与cPickle做同样的事情。

marshalcPickle实际上是完全不同的,您不能同时获得快速保存和快速加载,因为快速保存意味着对数据结构进行更少的分析,这意味着将大量数据保存到磁盘。

关于marshal可能与其他版本的Python不兼容的事实,您通常应该使用cPickle

“这不是一个通用的”持久性“模块。要通过RPC调用实现Python对象的一般持久性和传输,请参阅模块的筛选和搁置。封送模块的存在主要是为了支持读取和编写.pyc文件的Python模块的”伪编译“代码。因此,Python维护人员保留在需要时以向后不兼容的方式修改封送件格式的权利。如果您正在序列化和反序列化Python对象,则使用泡菜模块代替--性能相当,版本独立性得到保证,并且泡菜支持的对象范围比封送组大得多。”(蟒蛇有关于元帅的文件)

票数 20
EN

Stack Overflow用户

发布于 2012-02-14 00:16:38

有些人可能认为这是一次黑客攻击,但我通过简单地用gc.disable()和gc.enable()包装泡菜转储调用获得了巨大的成功。例如,下面编写一个~50 to字典列表的代码片段从78秒到4秒不等。

代码语言:javascript
复制
#  not a complete example....
gc.disable()
cPickle.dump(params,fout,cPickle.HIGHEST_PROTOCOL)         
fout.close()               
gc.enable()
票数 14
EN

Stack Overflow用户

发布于 2011-12-23 11:24:48

这些基准之间的差异为加速cPickle提供了一个想法:

代码语言:javascript
复制
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

在第一种情况下,列表重复相同的字符串。第二个列表是等价的,但是每个字符串都是一个单独的对象,因为它是表达式的结果。现在,如果您最初是从外部源读取数据,则可以考虑某种类型的字符串去重复。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8514020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档