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

9 浏览
0 Comments

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

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

0
0 Comments

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

pickle是Python中的一种对象序列化和反序列化模块,用于将对象转化为字节流以便存储或传输。与直接加载文件相比,加载pickle对象通常需要更多的时间。产生这种差异的原因主要有两个方面:安全性问题和数据处理方式。

首先,pickle的安全性问题导致了其加载时间的延长。pickle实际上并没有序列化大量的数据,而是序列化一些数据和一堆指令,这些指令用于重新组装Python对象。这种机制使得pickle容易受到安全漏洞的影响,因此很多人认为pickle是不安全的,不建议使用。为了解决这个问题,Python提供了cPickle模块,它使用优化的C代码,比pickle的加载速度更快。

其次,pickle的数据处理方式也导致了加载时间的延长。相对于直接存储对象本身,一般情况下pickle可以占用更少的存储空间。但是,由于pickle使用的指令集可能非常大,因此pickle的文件大小可能会比JSON更大。JSON的优势在于它以人类可读的字符串形式存储数据,但它无法序列化pickle和cPickle可以序列化的那么多种类型的对象。因此,使用pickle可以在灵活性和人类可读性之间进行权衡。

除了上述原因外,选择pickle而不是JSON的另一个好处是可以轻松扩展pickle,即注册一个新的序列化方法来序列化pickle无法序列化的对象。Python提供了几种方式来实现这一点,比如`__getstate__`和`__setstate__`方法以及`copy_reg`方法。通过使用这些方法,人们可以扩展pickle以序列化大多数Python对象,例如dill模块。

需要注意的是,pickle虽然不能恢复对象到相同的内存位置,但它可以使对象恢复到与序列化之前相同的状态。如果想了解更多关于为什么人们使用pickle的原因,可以参考以下链接:

- [Python serialization - Why pickle?](https://stackoverflow.com/questions/8968884)

- [Parallelism and Serialization](http://matthewrocklin.com/blog/work/2013/12/05/Parallelism-and-Serialization/)

0
0 Comments

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

这个问题的出现的原因是因为Python 2.7默认使用的是纯Python实现的pickle模块,而不是更快的C实现。相反,Python 2.7默认使用的是经过优化的C实现的json模块。所以,你实际上是在比较纯Python反序列化器和优化的C反序列化器。即使序列化格式相同,这也不是一个公平的比较。

解决方法是使用C实现的pickle模块,即cPickle。cPickle比纯Python实现的pickle更快,可以显著提高反序列化的速度。可以通过以下代码来使用cPickle:

import cPickle as pickle
# 加载pickle对象
with open('file.pickle', 'rb') as f:
    obj = pickle.load(f)

另外,如果你在加载pickle对象时遇到了性能问题,可以尝试使用更高的协议版本。pickle模块支持多个协议版本,每个版本都有不同的性能特性。可以通过设置pickle.dump()的protocol参数来指定协议版本,例如:

import cPickle as pickle
# 保存pickle对象
with open('file.pickle', 'wb') as f:
    pickle.dump(obj, f, protocol=pickle.HIGHEST_PROTOCOL)
# 加载pickle对象
with open('file.pickle', 'rb') as f:
    obj = pickle.load(f)

使用最高的协议版本可以提高性能,但同时也会增加序列化文件的大小。根据实际情况,可以根据性能和文件大小之间的权衡选择适当的协议版本。

要解决加载pickle对象比加载文件慢的问题,可以使用C实现的pickle模块(cPickle),并尝试使用更高的协议版本来提高性能。

0