Skip to content

Commit bc4228f

Browse files
committed
update benchmark PyPy
1 parent 94c96c9 commit bc4228f

3 files changed

Lines changed: 57 additions & 8 deletions

File tree

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ pip install msgpack-streams
1010

1111
## Benchmarks
1212

13-
Average of 50 iterations each on a 3.77 MB payload, pure Python
14-
(`MSGPACK_PUREPYTHON=1`).
13+
Average of 50 iterations each on a 3.77 MB payload, pure Python 3.14.3 (with
14+
`MSGPACK_PUREPYTHON=1`).
1515

1616
| Implementation | Operation | Speedup vs msgpack |
1717
| ------------------------------- | --------- | ------------------ |
@@ -20,6 +20,14 @@ Average of 50 iterations each on a 3.77 MB payload, pure Python
2020
| msgpack-streams `pack` | encode | 1.84x |
2121
| msgpack-streams `pack_stream` | encode | 1.69x |
2222

23+
For PyPy 3.11.15, the pure Python performance is comparable to the `msgpack` C
24+
extension.
25+
26+
| Implementation | Operation | Speedup vs msgpack (C) |
27+
| ------------------------ | --------- | ---------------------- |
28+
| msgpack-streams `unpack` | decode | 0.95x |
29+
| msgpack-streams `pack` | encode | 1.96x |
30+
2331
## Usage
2432

2533
```python
@@ -99,9 +107,11 @@ Use `ext_hook` to pack custom types as extensions, and `ext_hook` to decode them
99107
back:
100108

101109
```python
110+
from dataclasses import dataclass
102111
from msgpack_streams import ExtType, pack, unpack
103112
from fmtspec import decode, encode, types # https://pypi.org/project/fmtspec/
104113

114+
@dataclass
105115
class Point:
106116
EXT_CODE = 10
107117

@@ -110,23 +120,23 @@ class Point:
110120
"y": types.u32,
111121
}
112122

113-
def __init__(self, x: int, y: int):
114-
self.x, self.y = x, y
123+
x: int
124+
y: int
115125

116126
def unknown_type_hook(obj):
117127
if isinstance(obj, Point):
118128
return ExtType(Point.EXT_CODE, encode(obj))
119-
return None # unsupported type TypeError
129+
return None # unsupported type -> TypeError
120130

121131
def ext_hook(ext):
122132
if ext.code == Point.EXT_CODE:
123133
return decode(ext.data, shape=Point)
124-
return None # unknown keep as ExtType
134+
return None # unknown -> keep as ExtType
125135

126136
pt = Point(1, 2)
127137
packed = pack(pt, ext_hook=unknown_type_hook)
128138
result, _ = unpack(packed, ext_hook=ext_hook)
129-
assert result.x == pt.x and result.y == pt.y
139+
assert pt == result
130140
```
131141

132142
## API reference

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ classifiers = [
77
"Operating System :: OS Independent",
88
"Typing :: Typed",
99
"Development Status :: 5 - Production/Stable",
10+
"Programming Language :: Python :: Implementation :: CPython",
11+
"Programming Language :: Python :: Implementation :: PyPy",
1012
]
1113
keywords = [
1214
"msgpack",

scripts/bench.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import gc
12
import os
23

34
# set before importing `msgpack`
@@ -68,6 +69,9 @@ def serialize_other(obj, mapped):
6869
fd.write(packb(obj))
6970

7071

72+
RAW_OBJ = stream(False)
73+
RAW_DATA = pack(RAW_OBJ)
74+
7175
if __name__ == "__main__":
7276
parser = argparse.ArgumentParser()
7377
parser.add_argument("-n", "--number", type=int, default=25, help="Number of runs")
@@ -77,40 +81,73 @@ def serialize_other(obj, mapped):
7781
_globals = {
7882
"main": main,
7983
"stream": stream,
84+
"raw": unpack,
8085
"other": other,
86+
"other_raw": unpackb,
87+
"data": RAW_DATA,
8188
"mapped": args.mapped,
8289
}
8390

8491
_serialize = {
8592
"main": serialize_main,
8693
"stream": serialize_stream,
94+
"raw": pack,
8795
"other": serialize_other,
88-
"obj": stream(False),
96+
"other_raw": packb,
97+
"obj": RAW_OBJ,
8998
"mapped": args.mapped,
9099
}
91100

101+
gc.disable()
102+
92103
t_main = timeit.timeit("main(mapped)", number=args.number, globals=_globals)
93104
t_stream = timeit.timeit("stream(mapped)", number=args.number, globals=_globals)
105+
t_raw = timeit.timeit("raw(data)", number=args.number, globals=_globals)
94106
t_other = timeit.timeit("other(mapped)", number=args.number, globals=_globals)
107+
t_other_raw = timeit.timeit(
108+
"other_raw(data, strict_map_key=False)", number=args.number, globals=_globals
109+
)
110+
111+
gc.enable()
112+
gc.collect()
95113

96114
print(
97115
f"main: {t_main:.6f}s total, {t_main / args.number:.6f}s per call ({t_other / t_main:.2f}x speedup vs msgpack)"
98116
)
99117
print(
100118
f"stream: {t_stream:.6f}s total, {t_stream / args.number:.6f}s per call ({t_other / t_stream:.2f}x speedup vs msgpack)"
101119
)
120+
print(
121+
f"raw (unpack bytes): {t_raw:.6f}s total, {t_raw / args.number:.6f}s per call ({t_other_raw / t_raw:.2f}x speedup vs msgpack raw)"
122+
)
102123
print(f"other (msgpack): {t_other:.6f}s total, {t_other / args.number:.6f}s per call")
124+
print(
125+
f"other_raw (unpackb bytes): {t_other_raw:.6f}s total, {t_other_raw / args.number:.6f}s per call"
126+
)
127+
128+
gc.disable()
103129

104130
t_main_s = timeit.timeit("main(obj, mapped)", number=args.number, globals=_serialize)
105131
t_stream_s = timeit.timeit("stream(obj, mapped)", number=args.number, globals=_serialize)
132+
t_raw_s = timeit.timeit("raw(obj)", number=args.number, globals=_serialize)
106133
t_other_s = timeit.timeit("other(obj, mapped)", number=args.number, globals=_serialize)
134+
t_other_raw_s = timeit.timeit("other_raw(obj)", number=args.number, globals=_serialize)
135+
136+
gc.enable()
137+
gc.collect()
107138

108139
print(
109140
f"main serialize: {t_main_s:.6f}s total, {t_main_s / args.number:.6f}s per call ({t_other_s / t_main_s:.2f}x speedup vs msgpack)"
110141
)
111142
print(
112143
f"stream serialize: {t_stream_s:.6f}s total, {t_stream_s / args.number:.6f}s per call ({t_other_s / t_stream_s:.2f}x speedup vs msgpack)"
113144
)
145+
print(
146+
f"raw serialize (pack bytes): {t_raw_s:.6f}s total, {t_raw_s / args.number:.6f}s per call ({t_other_raw_s / t_raw_s:.2f}x speedup vs msgpack raw)"
147+
)
114148
print(
115149
f"other serialize (msgpack): {t_other_s:.6f}s total, {t_other_s / args.number:.6f}s per call"
116150
)
151+
print(
152+
f"other_raw serialize (packb bytes): {t_other_raw_s:.6f}s total, {t_other_raw_s / args.number:.6f}s per call"
153+
)

0 commit comments

Comments
 (0)