为什么Pickle协议4的文件大小是协议3的两倍而速度没有提升?
我在测试Python 3.4的时候,发现pickle模块有了新的协议。所以我对比了两个协议的性能。
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)
测试1的结果:在6.473秒内进行了2000007次函数调用。
测试2的结果:在6.740秒内进行了2000007次函数调用。
协议4的速度比协议3稍微慢一点,但这个差别可以忽略不计。不过,硬盘的使用情况却差别很大。
使用pickle3时,占用了7,868,672字节。
使用pickle4时,占用了16,868,672字节。
这让我觉得很奇怪,我继续深入研究。看了PEP3154后,我大致明白了这个协议的内容。
对于元组(1,2,3,4,5,6,7)在协议3中的表现:
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
对于元组(1,2,3,4,5,6,7)在协议4中的表现:
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
协议3的解码器在读取到第17个位置之前,无法知道数据的长度。
而在协议4中,从第2个位置到第18个位置,有一个头部信息显示了数据的长度。
不过,我还是不明白,为什么我在极端情况下要付出几乎双倍的硬盘使用量,却速度差不多或者可能更慢?
1 个回答
2
你在处理整数(ints)。对于这么简单的数据类型,提前知道结构的大小其实没有什么好处。可是对于更复杂的结构,知道框架的大小可以大大提高处理速度。此外,协议4对64位系统放宽了很多限制。