Commit 0b663377 authored by Jason Madden's avatar Jason Madden

Stop parsing the struct formats each time.

This makes the test runs in pure_python mode 15s faster.

Microbenchmarks on CPython 2.7.14:

$ python -m perf timeit -s 'from struct import pack,unpack' 'unpack("i", pack("i", 123456))'
.....................
Mean +- std dev: 365 ns +- 12 ns

$ python -m perf timeit -s 'from struct import Struct; s = Struct("i"); unpack=s.unpack; pack=s.pack' 'unpack(pack(123456))'
.....................
Mean +- std dev: 251 ns +- 9 ns

No appreciable difference on PyPy.
parent 5ddd0442
...@@ -14,8 +14,7 @@ ...@@ -14,8 +14,7 @@
"""Python BTree implementation """Python BTree implementation
""" """
from struct import pack from struct import Struct
from struct import unpack
from struct import error as struct_error from struct import error as struct_error
from persistent import Persistent from persistent import Persistent
...@@ -1496,10 +1495,16 @@ def multiunion(set_type, seqs): ...@@ -1496,10 +1495,16 @@ def multiunion(set_type, seqs):
def to_ob(self, v): def to_ob(self, v):
return v return v
def _packer_unpacker(struct_format):
s = Struct(struct_format)
return s.pack, s.unpack
int_pack, int_unpack = _packer_unpacker('i')
def to_int(self, v): def to_int(self, v):
try: try:
# XXX Python 2.6 doesn't truncate, it spews a warning. # XXX Python 2.6 doesn't truncate, it spews a warning.
if not unpack("i", pack("i", v))[0] == v: #pragma: no cover if not int_unpack(int_pack(v))[0] == v: #pragma: no cover
raise TypeError('32-bit integer expected') raise TypeError('32-bit integer expected')
except (struct_error, except (struct_error,
OverflowError, #PyPy OverflowError, #PyPy
...@@ -1508,17 +1513,22 @@ def to_int(self, v): ...@@ -1508,17 +1513,22 @@ def to_int(self, v):
return int(v) return int(v)
float_pack = _packer_unpacker('f')[0]
def to_float(self, v): def to_float(self, v):
try: try:
pack("f", v) float_pack(v)
except struct_error: except struct_error:
raise TypeError('float expected') raise TypeError('float expected')
return float(v) return float(v)
long_pack, long_unpack = _packer_unpacker('q')
def to_long(self, v): def to_long(self, v):
try: try:
# XXX Python 2.6 doesn't truncate, it spews a warning. # XXX Python 2.6 doesn't truncate, it spews a warning.
if not unpack("q", pack("q", v))[0] == v: #pragma: no cover if not long_unpack(long_pack(v))[0] == v: #pragma: no cover
if isinstance(v, int_types): if isinstance(v, int_types):
raise ValueError("Value out of range", v) raise ValueError("Value out of range", v)
raise TypeError('64-bit integer expected') raise TypeError('64-bit integer expected')
......
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