You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Given the close similarity between msgspec.Struct and dataclasses.dataclass, am curious to what extent dataclasses can be used with msgspec and what this entails.
Dataclasses aren't natively supported, but could be handled with a custom enc_hook and dec_hook. However, this will be slow (much slower than using a msgspec.Struct or using a raw dict). While structs and dataclasses have similar apis, its the internal design of struct types that makes them so fast. We could add native support for dataclasses which would put them somewhere between structs and dicts in encode speed (faster than a dict, slower than a struct), but for decoding they'd still be slower than a dict. If possible I recommend people just use structs - they're fast and support most of the things people want in dataclasses.
Hi there. So, while trying to make the switch from orjson to msgspec for Starlite, I encountered this issue. The main concern here is performance really. Dataclasses are natively supported by orjson; Their serialization is therefore quite fast.
What this means for us is, that making the switch to msgspec would be a massive drop in performance for our users when dataclasses are being used.
You can see below a simple benchmark result comparing the branch with orjson and the branch with msgspec.
I'm not sure how much work implementing dataclasses support would be, I just wanted to let you know of this use case where dataclass support is kinda vital, so you can consider if you deem it to be worth the effort.
Thanks for the ping (and the nice benchmark plot). I've actually been revisiting this opinion, and I think you've convinced me that adding simple support for dataclasses is worth it. Now that we have support for TypedDict and NamedTuple objects, asking for dataclass support isn't that far off. And compatibility with orjson is a convincing use case. Users really should use msgspec.Struct objects instead when possible (they're much faster, and have fewer weird edge cases than dataclasses), but we can do a decent job with encoding/decoding dataclasses too.
I spent some time this evening experimenting with an implementation, and I'm pretty happy with the results. Encoding time is already much faster than what orjson provides, especially when slots=True is set:
In [1]: importmsgspec, orjsonIn [2]: fromdataclassesimportdataclassIn [3]: enc=msgspec.json.Encoder()
In [4]: @dataclass
...: classNoSlots:
...: field_one: int
...: field_two: int
...:
In [5]: @dataclass(slots=True)
...: classSlots:
...: field_one: int
...: field_two: int
...:
In [6]: no_slots= [NoSlots(i-1, i+1) foriinrange(10000)]
In [7]: with_slots= [Slots(i-1, i+1) foriinrange(10000)]
In [8]: %timeitenc.encode(no_slots) # msgspec, no slots561µs ± 2.04µsperloop (mean ± std. dev. of7runs, 1,000loopseach)
In [9]: %timeitorjson.dumps(no_slots) # orjson, no slots834µs ± 1.69µsperloop (mean ± std. dev. of7runs, 1,000loopseach)
In [10]: %timeitenc.encode(with_slots) # msgspec, with slots779µs ± 20µsperloop (mean ± std. dev. of7runs, 1,000loopseach)
In [11]: %timeitorjson.dumps(with_slots) # orjson, with slots3.71ms ± 90.1µsperloop (mean ± std. dev. of7runs, 100loopseach)
In [12]: classStruct(msgspec.Struct):
...: field_one: int
...: field_two: int
...:
In [13]: structs= [Struct(i-1, i+1) foriinrange(10000)]
In [14]: %timeitenc.encode(structs) # msgspec structs356µs ± 307nsperloop (mean ± std. dev. of7runs, 1,000loopseach)
I have JSON encoding done already. Decoding will take a bit more work, but I'd estimate done in the next week or two. I'll reopen this for now as a reminder.
Reacted by jakirkham, Janek Nouvertné and pavdwest
Ok, #218 is in - msgspec now supports encoding/decoding dataclasses. This came together a lot quicker than I expected, and was pretty fun to work on. They're not as performant or featureful as Struct types, but perforamance isn't bad (especially for encoding).
I have a few other small fixups I'd like to get in, I'd expect a release sometime next week.
Reacted by jakirkham, Janek Nouvertné and Peter Schutt
Activity
goodboy commentedon Feb 6, 2022
Pretty sure you can write a custom codec to handle them as per: https://jcristharif.com/msgspec/extending.html#mapping-to-from-native-types
jcrist commentedon Feb 8, 2022
Dataclasses aren't natively supported, but could be handled with a custom
enc_hookanddec_hook. However, this will be slow (much slower than using amsgspec.Structor using a rawdict). While structs and dataclasses have similar apis, its the internal design of struct types that makes them so fast. We could add native support for dataclasses which would put them somewhere between structs and dicts in encode speed (faster than a dict, slower than a struct), but for decoding they'd still be slower than a dict. If possible I recommend people just use structs - they're fast and support most of the things people want in dataclasses.old-ocean-creature commentedon Jun 19, 2022
This is true except there is an ecosystem of tooling around dataclasses, adopting
msgspec.Structmeans disconnecting from that ecosystemjcrist commentedon Jun 19, 2022
What libraries/tools are you thinking of that require dataclasses that you'd also like to use with msgspec?
provinzkraut commentedon Nov 30, 2022
Hi there. So, while trying to make the switch from orjson to msgspec for Starlite, I encountered this issue. The main concern here is performance really. Dataclasses are natively supported by orjson; Their serialization is therefore quite fast.
What this means for us is, that making the switch to msgspec would be a massive drop in performance for our users when dataclasses are being used.
You can see below a simple benchmark result comparing the branch with orjson and the branch with msgspec.
I'm not sure how much work implementing dataclasses support would be, I just wanted to let you know of this use case where dataclass support is kinda vital, so you can consider if you deem it to be worth the effort.
jcrist commentedon Dec 1, 2022
Thanks for the ping (and the nice benchmark plot). I've actually been revisiting this opinion, and I think you've convinced me that adding simple support for dataclasses is worth it. Now that we have support for
TypedDictandNamedTupleobjects, asking for dataclass support isn't that far off. And compatibility withorjsonis a convincing use case. Users really should usemsgspec.Structobjects instead when possible (they're much faster, and have fewer weird edge cases than dataclasses), but we can do a decent job with encoding/decoding dataclasses too.I spent some time this evening experimenting with an implementation, and I'm pretty happy with the results. Encoding time is already much faster than what orjson provides, especially when
slots=Trueis set:I have JSON encoding done already. Decoding will take a bit more work, but I'd estimate done in the next week or two. I'll reopen this for now as a reminder.
Goldziher commentedon Dec 1, 2022
fantastic! were are eagerly awaiting 😉
provinzkraut commentedon Dec 1, 2022
@jcrist Thank you for your fantastic work on this and your responsiveness to the issues we raised here in general!
jcrist commentedon Dec 2, 2022
Ok, #218 is in -
msgspecnow supports encoding/decoding dataclasses. This came together a lot quicker than I expected, and was pretty fun to work on. They're not as performant or featureful asStructtypes, but perforamance isn't bad (especially for encoding).I have a few other small fixups I'd like to get in, I'd expect a release sometime next week.
jakirkham commentedon Dec 2, 2022
Thanks Jim! 🙏
provinzkraut commentedon Dec 2, 2022
It's working fantastic! I ran the benchmark again and we can see some real improvements!
Fix `Meta(pattern=..)` memory leak / corruption (msgspec#1256)