jcrist · GitHub

A simple encoding benchmark:

In [1]: import msgspec, orjson
In [2]: from dataclasses import dataclass
In [3]: enc = msgspec.json.Encoder()
In [4]: @dataclass
   ...: class NoSlots:
   ...:     field_one: int
   ...:     field_two: int
   ...:
In [5]: @dataclass(slots=True)
   ...: class Slots:
   ...:     field_one: int
   ...:     field_two: int
   ...:
In [6]: no_slots = [NoSlots(i - 1, i + 1) for i in range(10000)]
In [7]: with_slots = [Slots(i - 1, i + 1) for i in range(10000)]
In [8]: %timeit enc.encode(no_slots)  # msgspec, no slots
561 µs ± 2.04 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
In [9]: %timeit orjson.dumps(no_slots)  # orjson, no slots
834 µs ± 1.69 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
In [10]: %timeit enc.encode(with_slots)  # msgspec, with slots
779 µs ± 20 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
In [11]: %timeit orjson.dumps(with_slots)  # orjson, with slots
3.71 ms ± 90.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [12]: class Struct(msgspec.Struct):
    ...:     field_one: int
    ...:     field_two: int
    ...:
In [13]: structs = [Struct(i - 1, i + 1) for i in range(10000)]
In [14]: %timeit enc.encode(structs)  # msgspec structs
356 µs ± 307 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

For these type definitions on my machine:

  • msgspec encodes dataclasses to JSON 1.5x faster than orjson
  • msgspec encodes dataclasses with slots=True to JSON 5x faster than orjson
  • dataclasses with slots=True are slower to encode than slots=False. This has to do with object layouts and what information is efficiently accessible on the type definition.
  • msgspec encodes Struct types 1.5x faster than dataclasses

Read the original on github.com ↗