Commit 5f188c02 authored by Guido van Rossum's avatar Guido van Rossum

Got rid of mdumps; I timed it, and struct.pack("<i", x) is more than

40% faster than marshal.dumps(x)[1:]!  (That's not counting the
module attribute lookups, which can be avoided in either case.)
parent 56bed534
...@@ -45,7 +45,6 @@ compatible_formats = ["1.0", # Original protocol 0 ...@@ -45,7 +45,6 @@ compatible_formats = ["1.0", # Original protocol 0
"2.0", # Protocol 2 "2.0", # Protocol 2
] # Old format versions we can read ] # Old format versions we can read
mdumps = marshal.dumps
mloads = marshal.loads mloads = marshal.loads
class PickleError(Exception): class PickleError(Exception):
...@@ -220,25 +219,22 @@ class Pickler: ...@@ -220,25 +219,22 @@ class Pickler:
self.memo[id(obj)] = memo_len, obj self.memo[id(obj)] = memo_len, obj
# Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i. # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
def put(self, i): def put(self, i, pack=struct.pack):
if self.bin: if self.bin:
s = mdumps(i)[1:]
if i < 256: if i < 256:
return BINPUT + s[0] return BINPUT + chr(i)
else:
return LONG_BINPUT + s return LONG_BINPUT + pack("<i", i)
return PUT + `i` + '\n' return PUT + `i` + '\n'
# Return a GET (BINGET, LONG_BINGET) opcode string, with argument i. # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
def get(self, i): def get(self, i, pack=struct.pack):
if self.bin: if self.bin:
s = mdumps(i)[1:]
if i < 256: if i < 256:
return BINGET + s[0] return BINGET + chr(i)
else:
return LONG_BINGET + s return LONG_BINGET + pack("<i", i)
return GET + `i` + '\n' return GET + `i` + '\n'
...@@ -362,24 +358,25 @@ class Pickler: ...@@ -362,24 +358,25 @@ class Pickler:
self.write(object and TRUE or FALSE) self.write(object and TRUE or FALSE)
dispatch[bool] = save_bool dispatch[bool] = save_bool
def save_int(self, object): def save_int(self, object, pack=struct.pack):
if self.bin: if self.bin:
# If the int is small enough to fit in a signed 4-byte 2's-comp # If the int is small enough to fit in a signed 4-byte 2's-comp
# format, we can store it more efficiently than the general # format, we can store it more efficiently than the general
# case. # case.
# First one- and two-byte unsigned ints:
if object >= 0:
if object < 0xff:
self.write(BININT1 + chr(object))
return
if object < 0xffff:
self.write(BININT2 + chr(object&0xff) + chr(object>>8))
return
# Next check for 4-byte signed ints:
high_bits = object >> 31 # note that Python shift sign-extends high_bits = object >> 31 # note that Python shift sign-extends
if high_bits == 0 or high_bits == -1: if high_bits == 0 or high_bits == -1:
# All high bits are copies of bit 2**31, so the value # All high bits are copies of bit 2**31, so the value
# fits in a 4-byte signed int. # fits in a 4-byte signed int.
i = mdumps(object)[1:] self.write(BININT + pack("<i", object))
assert len(i) == 4
if i[-2:] == '\000\000': # fits in 2-byte unsigned int
if i[-3] == '\000': # fits in 1-byte unsigned int
self.write(BININT1 + i[0])
else:
self.write(BININT2 + i[:2])
else:
self.write(BININT + i)
return return
# Text pickle, or int too big to fit in signed 4-byte format. # Text pickle, or int too big to fit in signed 4-byte format.
self.write(INT + `object` + '\n') self.write(INT + `object` + '\n')
...@@ -396,24 +393,23 @@ class Pickler: ...@@ -396,24 +393,23 @@ class Pickler:
self.write(FLOAT + `object` + '\n') self.write(FLOAT + `object` + '\n')
dispatch[FloatType] = save_float dispatch[FloatType] = save_float
def save_string(self, object): def save_string(self, object, pack=struct.pack):
if self.bin: if self.bin:
n = len(object) n = len(object)
if n < 256: if n < 256:
self.write(SHORT_BINSTRING + chr(n) + object) self.write(SHORT_BINSTRING + chr(n) + object)
else: else:
self.write(BINSTRING + mdumps(n)[1:] + object) self.write(BINSTRING + pack("<i", n) + object)
else: else:
self.write(STRING + `object` + '\n') self.write(STRING + `object` + '\n')
self.memoize(object) self.memoize(object)
dispatch[StringType] = save_string dispatch[StringType] = save_string
def save_unicode(self, object): def save_unicode(self, object, pack=struct.pack):
if self.bin: if self.bin:
encoding = object.encode('utf-8') encoding = object.encode('utf-8')
n = len(encoding) n = len(encoding)
s = mdumps(n)[1:] self.write(BINUNICODE + pack("<i", n) + encoding)
self.write(BINUNICODE + s + encoding)
else: else:
object = object.replace("\\", "\\u005c") object = object.replace("\\", "\\u005c")
object = object.replace("\n", "\\u000a") object = object.replace("\n", "\\u000a")
...@@ -423,17 +419,17 @@ class Pickler: ...@@ -423,17 +419,17 @@ class Pickler:
if StringType == UnicodeType: if StringType == UnicodeType:
# This is true for Jython # This is true for Jython
def save_string(self, object): def save_string(self, object, pack=struct.pack):
unicode = object.isunicode() unicode = object.isunicode()
if self.bin: if self.bin:
if unicode: if unicode:
object = object.encode("utf-8") object = object.encode("utf-8")
l = len(object) l = len(object)
s = mdumps(l)[1:]
if l < 256 and not unicode: if l < 256 and not unicode:
self.write(SHORT_BINSTRING + s[0] + object) self.write(SHORT_BINSTRING + chr(l) + object)
else: else:
s = pack("<i", l)
if unicode: if unicode:
self.write(BINUNICODE + s + object) self.write(BINUNICODE + s + object)
else: else:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment