Py3k supports pickling directly from the slot structure of a class, without requiring a __getstate__ override. Thus
|
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) |
is unneeded. That code exists- I think- as part of the bridge over py2k old/new style. Either way, it's dead.
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 is allow_mutations(object.__setsetate__), roughly. It'll defer the core work steps to python while allowing mutation. This however will still lead to python invoking the Immutable.__setattr__ for every object, which isn't efficient. This is still faster than what's in place now for SlotsPicklingMixin however.
- A solution there is to special case
__setstate__ so it installs a function that is the loop of object.__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.
Py3k supports pickling directly from the slot structure of a class, without requiring a
__getstate__override. Thussnakeoil/src/snakeoil/klass/__init__.py
Lines 420 to 430 in d3438eb
Removing that removes at least 2 levels of python function calls in all serialize usage of those consumers- likely more. The underlying
get_slots_ofdoesn'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
SlotsPicklingMixincan 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
Immutablestyle class protections. There's two implementations possible here:__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.__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.