Skip to content

Commit 678d331

Browse files
committed
refactor / optimize
1 parent 3f9b12e commit 678d331

7 files changed

Lines changed: 299 additions & 242 deletions

File tree

scripts/bench.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import os
2+
3+
# set before importing `msgpack`
4+
os.environ["MSGPACK_PUREPYTHON"] = "1"
5+
6+
from msgpack_stream import unpack, unpack_stream
7+
from mmap import mmap, ACCESS_READ
8+
import argparse
9+
import timeit
10+
11+
from msgpack import unpackb
12+
13+
14+
FILE = "scripts/obj.msgpack"
15+
16+
17+
def main(mapped):
18+
with open(FILE, "rb", buffering=0) as fd:
19+
if mapped:
20+
with mmap(fd.fileno(), 0, access=ACCESS_READ) as mm:
21+
return unpack(mm.read())
22+
else:
23+
return unpack(fd.read())
24+
25+
26+
def stream(mapped):
27+
with open(FILE, "rb", buffering=0) as fd:
28+
if mapped:
29+
with mmap(fd.fileno(), 0, access=ACCESS_READ) as mm:
30+
return unpack_stream(mm)
31+
else:
32+
return unpack_stream(fd)
33+
34+
35+
def other(mapped):
36+
with open(FILE, "rb", buffering=0) as fd:
37+
if mapped:
38+
with mmap(fd.fileno(), 0, access=ACCESS_READ) as mm:
39+
return unpackb(mm.read(), strict_map_key=False)
40+
else:
41+
return unpackb(fd.read(), strict_map_key=False)
42+
43+
44+
if __name__ == "__main__":
45+
_globals = {
46+
"main": main,
47+
"stream": stream,
48+
"other": other,
49+
}
50+
parser = argparse.ArgumentParser()
51+
parser.add_argument("-n", "--number", type=int, default=25, help="Number of runs")
52+
args = parser.parse_args()
53+
54+
t_main = timeit.timeit("main(True)", number=args.number, globals=_globals)
55+
# this needs to be mmap for good performance
56+
t_stream = timeit.timeit("stream(True)", number=args.number, globals=_globals)
57+
t_other = timeit.timeit("other(True)", number=args.number, globals=_globals)
58+
59+
print(f"main: {t_main:.6f}s total, {t_main / args.number:.6f}s per call")
60+
print(f"stream: {t_stream:.6f}s total, {t_stream / args.number:.6f}s per call")
61+
print(f"other: {t_other:.6f}s total, {t_other / args.number:.6f}s per call")

scripts/obj.msgpack

3.77 MB
Binary file not shown.

src/msgpack_stream/__init__.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
11
"""Pure Python stream based implementation of msgpack"""
22

3-
from ._io import pack as packb, unpack as unpackb
4-
from ._msgpack import msgpack_t
5-
6-
7-
def pack(obj):
8-
"""Pack object into data."""
9-
return packb(msgpack_t, obj)
10-
11-
12-
def unpack(data):
13-
"""Unpack data into object."""
14-
return unpackb(msgpack_t, data)
3+
from ._io import pack as pack, unpack as unpack
4+
from ._msgpack import pack_stream as pack_stream, unpack_stream as unpack_stream

src/msgpack_stream/_io.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
import io
22

3+
from ._msgpack import pack_stream, unpack_stream
34

4-
class container(dict):
5-
__getattr__ = dict.__getitem__
6-
__setattr__ = dict.__setitem__
7-
__delattr__ = dict.__delitem__
85

9-
10-
def pack(typ, obj):
11-
stream = io.BytesIO()
12-
typ.pack(stream, obj)
13-
data = stream.getvalue()
14-
stream.close()
6+
def pack(obj):
7+
"""Pack object into data."""
8+
with io.BytesIO() as stream:
9+
pack_stream(stream, obj)
10+
data = stream.getvalue()
1511
return data
1612

1713

18-
def unpack(typ, data):
19-
stream = io.BytesIO(data)
20-
obj = typ.unpack(stream)
21-
extra_data = stream.read()
22-
if extra_data:
23-
raise RuntimeError("too much data", extra_data)
24-
stream.close()
25-
return obj
14+
def unpack(data):
15+
"""Unpack data into object."""
16+
with io.BytesIO(data) as stream:
17+
obj = unpack_stream(stream)
18+
excess_data = stream.read()
19+
return obj, excess_data

0 commit comments

Comments
 (0)