为什么加载pickle对象比加载文件慢得多?

4
我注意到使用pickle加载5000个对象的字典需要很长时间(几分钟)-但是加载包含5000个实体的json文件只需要很短的时间(几秒钟)。我知道通常对象带有一些开销-在面向对象编程中,跟踪这些对象的开销是使用它们的成本的一部分。但为什么加载pickled对象需要这么长时间?底层发生了什么事情?序列化对象与仅将其数据写入文件相比有哪些成本? pickle是否将对象恢复到内存中的相同位置或其他位置?(也许将其他对象移开)。如果序列化加载速度较慢(至少pickle是),那么好处是什么?

1
你是否正在使用二进制协议的cPickle? - John La Rooy
@gnibbler 不,我不是。 - bernie2436
2
你需要发布示例代码以展示你实际上正在比较什么以及如何计时。如果没有它,你就要求我们去猜测你是如何进行比较计时的,以及你使用的pickle和JSON反序列化器的哪些实现。 - Dan Lenski
2个回答

4
假设您正在使用Python 2.7标准的pickle和json模块...

因此,您基本上是在比较纯Python的反序列化程序和优化的C反序列化程序。即使序列化格式相同,这也不是一个公平的比较。


我和 OP 有同样的问题,比较逐行加载文本文件(每行一个小对象)与加载对象列表的 pickle。我使用 cPickle,二进制格式和最高协议,但反序列化比读取和重建慢了50%。 - Nikana Reklawyks

2

有一些关于特定对象序列化的速度比较,比较JSON、pickle和cPickle。每种格式下每个对象的速度都会不同。通常情况下,JSON比pickle更快,而且你经常听到不要使用pickle,因为它是不安全的。安全问题和一些速度滞后的原因在于pickle实际上并没有序列化很多数据——相反,它序列化了一些数据和一堆指令,这些指令用于组装Python对象。如果你曾经看过dis模块,你会看到pickle为每个对象使用的指令类型。cPickle像json一样,并不是纯Python,而是利用了优化的C,所以它通常更快。

总体而言,pickle应该比存储对象本身占用更少的空间——但是,某些指令集可能非常大。JSON倾向于更小……并且是人类可读的……然而,由于json将所有内容都存储为人类可读的字符串……它不能序列化与pickle和cPickle可以序列化的那么多种不同的对象。因此,权衡的是json提供了“安全性”(或者说是灵活性不足,取决于你的观点)和人类可读性,而pickle则可以序列化更广泛的对象。

选择pickle(而不是json)的另一个好处是你可以轻松地扩展pickle,这意味着你可以注册一个新的方法来序列化pickle不知道如何序列化的对象。Python提供了几种方法来实现这一点……例如__getstate____setstate__以及copy_reg方法。使用这些方法,你会发现人们已经扩展了pickle以序列化大多数Python对象,例如dill。 pickling不会将对象恢复到相同的内存位置。然而,它确实重建了对象到与pickle时相同的状态(通常)。如果你想看看为什么人们使用pickle,请看这里:Python serialization - Why pickle?

http://nbviewer.ipython.org/gist/minrk/5241793

http://matthewrocklin.com/blog/work/2013/12/05/Parallelism-and-Serialization/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接