为什么 Pickle 协议 4 中的 Pickle 文件是协议 3 中的两倍,而速度却没有任何提升?

Lee*_*Lee 6 python python-3.x

我正在测试 Python 3.4,我注意到 pickle 模块有一个新协议。因此,我对 2 个协议进行了基准测试。

def test1():
    pickle3=open("pickle3","wb")
    for i in range(1000000):
        pickle.dump(i,pickle3,3)
    pickle3.close()
    pickle3=open("pickle3","rb")
    for i in range(1000000):
        pickle.load(pickle3)

def test2():
    pickle4=open("pickle4","wb")
    for i in range(1000000):
        pickle.dump(i, pickle4,4)
    pickle3.close()
    pickle4=open("pickle4","rb")
    for i in range(1000000):
        pickle.load(pickle4)
Run Code Online (Sandbox Code Playgroud)

test1 标记:6.473 秒内调用 2000007 次函数

test2 标记:6.740 秒内调用 2000007 次函数

协议4比协议3稍微慢一些。这种差异可以忽略不计。然而,硬盘的使用情况确实不同。

pickle3 使用 7,868,672 字节。

pickle4 使用 16,868,672 字节。

那没有理由。我继续挖掘。读完PEP3154后,我大致了解了该协议。

对于协议 3 的元组(1,2,3,4,5,6,7)

    0: \x80 PROTO      3
    2: (    MARK
    3: K        BININT1    1
    5: K        BININT1    2
    7: K        BININT1    3
    9: K        BININT1    4
   11: K        BININT1    5
   13: K        BININT1    6
   15: K        BININT1    7
   17: t        TUPLE      (MARK at 2)
   18: q    BINPUT     0
   20: .    STOP
Run Code Online (Sandbox Code Playgroud)

对于协议 4 的元组(1,2,3,4,5,6,7)

    0: \x80 PROTO      4
    2: \x95 FRAME      18
   11: (    MARK
   12: K        BININT1    1
   14: K        BININT1    2
   16: K        BININT1    3
   18: K        BININT1    4
   20: K        BININT1    5
   22: K        BININT1    6
   24: K        BININT1    7
   26: t        TUPLE      (MARK at 11)
   27: \x94 MEMOIZE
   28: .    STOP
Run Code Online (Sandbox Code Playgroud)

协议3的unpickler在读取到位置17之前无法知道数据的长度。

对于协议 4,从位置 2 到位置 18,有一个显示长度的标题。

但是,我仍然不明白为什么我付出了代价(在极端情况下几乎是硬盘使用量的两倍)但速度相同或可能更慢?

Dan*_*iel 2

你正在腌制整数。对于这样一个简单的数据类型,提前知道结构的大小没有任何好处。对于更复杂的结构,了解帧大小可以极大地提高处理速度。此外,协议4解除了64位系统的许多限制。