-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Py3k supports pickling directly from the slot structure of a class, without requiring a __getstate__ override. Thus
snakeoil/src/snakeoil/klass/__init__.py
Lines 420 to 430 in d3438eb
| class SlotsPicklingMixin: | |
| """Default pickling support for classes that use __slots__.""" | |
| __slots__ = () | |
| def __getstate__(self): | |
| return dict(get_attrs_of(self)) | |
| def __setstate__(self, state): | |
| for k, v in state.items(): | |
| object.__setattr__(self, k, v) |
Removing that removes at least 2 levels of python function calls in all serialize usage of those consumers- likely more. The underlying get_slots_of doesn't cache (some day, it may) so that's MRO walk of the class every instance serialization. It adds up, even if those functions themselves are fast.
Presumably this is sensitive to the slot ordering, but pickles are ephemeral- it's the consumers problem if they're changing swapping order and assuming the results to be stable. If that turns out to be an actual problem in real world code, a version of SlotsPicklingMixin can be implemented that forces the state to be by sorted slot order, assuming python doesn't already do this.
Removal of this is simple, exempting the usage of Immutable style class protections. There's two implementations possible here:
- is the class fully slotted, and no custom
__setstate__is in? Install a__setstate__that isallow_mutations(object.__setsetate__), roughly. It'll defer the core work steps to python while allowing mutation. This however will still lead to python invoking theImmutable.__setattr__for every object, which isn't efficient. This is still faster than what's in place now forSlotsPicklingMixinhowever. - A solution there is to special case
__setstate__so it installs a function that is the loop ofobject.__setattribute__. Single function frame for a state restore, and arguably more 'correct' in my view since deserializing an object shouldn't be going through it's custom__setattr__- marshalling is a lower level then runtime manipulation of objects.