diff options
author | Alexandre Vassalotti <alexandre@peadrop.com> | 2013-11-24 04:30:03 (GMT) |
---|---|---|
committer | Alexandre Vassalotti <alexandre@peadrop.com> | 2013-11-24 04:30:03 (GMT) |
commit | b6a2f2a0d1e32497ba1dbb12e4a16216ccb12913 (patch) | |
tree | 7fd17db5b4be11cc49f1f6f89aeb49a4a44ba328 /Lib/test/pickletester.py | |
parent | 1889623e1a49e38df6d10171e4a4256dfcb8916b (diff) | |
download | cpython-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.py | 39 |
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: |