summaryrefslogtreecommitdiffstats
path: root/Lib/test/pickletester.py
diff options
context:
space:
mode:
authorAlexandre Vassalotti <alexandre@peadrop.com>2013-11-24 04:30:03 (GMT)
committerAlexandre Vassalotti <alexandre@peadrop.com>2013-11-24 04:30:03 (GMT)
commitb6a2f2a0d1e32497ba1dbb12e4a16216ccb12913 (patch)
tree7fd17db5b4be11cc49f1f6f89aeb49a4a44ba328 /Lib/test/pickletester.py
parent1889623e1a49e38df6d10171e4a4256dfcb8916b (diff)
downloadcpython-b6a2f2a0d1e32497ba1dbb12e4a16216ccb12913.zip
cpython-b6a2f2a0d1e32497ba1dbb12e4a16216ccb12913.tar.gz
cpython-b6a2f2a0d1e32497ba1dbb12e4a16216ccb12913.tar.bz2
Make framing optional in pickle protocol 4.
This will allow us to control in the future whether to use framing or not. For example, we may want to turn it off for tiny pickle where it doesn't help. The change also improves performance slightly: ### fastpickle ### Min: 0.608517 -> 0.557358: 1.09x faster Avg: 0.798892 -> 0.694738: 1.15x faster Significant (t=3.45) Stddev: 0.17145 -> 0.12704: 1.3496x smaller Timeline: http://goo.gl/3xQE1J ### pickle_dict ### Min: 0.669920 -> 0.615271: 1.09x faster Avg: 0.733633 -> 0.645058: 1.14x faster Significant (t=5.05) Stddev: 0.12041 -> 0.02961: 4.0662x smaller Timeline: http://goo.gl/LpLSXI ### pickle_list ### Min: 0.397583 -> 0.368112: 1.08x faster Avg: 0.412784 -> 0.397223: 1.04x faster Significant (t=2.78) Stddev: 0.01518 -> 0.03653: 2.4068x larger Timeline: http://goo.gl/v39E59 ### unpickle_list ### Min: 0.692935 -> 0.594870: 1.16x faster Avg: 0.730012 -> 0.628395: 1.16x faster Significant (t=17.76) Stddev: 0.02720 -> 0.02995: 1.1012x larger Timeline: http://goo.gl/2P9AEt The following not significant results are hidden, use -v to show them: fastunpickle.
Diffstat (limited to 'Lib/test/pickletester.py')
-rw-r--r--Lib/test/pickletester.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 34e46f6..ffa1cfb 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -1353,6 +1353,45 @@ class AbstractPickleTests(unittest.TestCase):
n_frames = pickled.count(b'\x00\x00\x00\x00\x00')
self.assertGreaterEqual(n_frames, len(obj))
+ def test_optional_frames(self):
+ if pickle.HIGHEST_PROTOCOL < 4:
+ return
+
+ def remove_frames(pickled, keep_frame=None):
+ """Remove frame opcodes from the given pickle."""
+ frame_starts = []
+ # 1 byte for the opcode and 8 for the argument
+ frame_opcode_size = 9
+ for opcode, _, pos in pickletools.genops(pickled):
+ if opcode.name == 'FRAME':
+ frame_starts.append(pos)
+
+ newpickle = bytearray()
+ last_frame_end = 0
+ for i, pos in enumerate(frame_starts):
+ if keep_frame and keep_frame(i):
+ continue
+ newpickle += pickled[last_frame_end:pos]
+ last_frame_end = pos + frame_opcode_size
+ newpickle += pickled[last_frame_end:]
+ return newpickle
+
+ target_frame_size = 64 * 1024
+ num_frames = 20
+ obj = [bytes([i]) * target_frame_size for i in range(num_frames)]
+
+ for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
+ pickled = self.dumps(obj, proto)
+
+ frameless_pickle = remove_frames(pickled)
+ self.assertEqual(count_opcode(pickle.FRAME, frameless_pickle), 0)
+ self.assertEqual(obj, self.loads(frameless_pickle))
+
+ some_frames_pickle = remove_frames(pickled, lambda i: i % 2 == 0)
+ self.assertLess(count_opcode(pickle.FRAME, some_frames_pickle),
+ count_opcode(pickle.FRAME, pickled))
+ self.assertEqual(obj, self.loads(some_frames_pickle))
+
def test_nested_names(self):
global Nested
class Nested: