Alright, we support slot classes too now. The information below is valid for slot classes.
There is zero overhead for
Unfortunately, attribute access is much slower:
We wrap the original slot descriptor to block mutation, but we pass through access. However, this involves a pure Python method invocation. I don't know how to avoid this :(
It would probably help. We would need a customized version of this: https://github.com/python/cpython/blob/fff9a31a91283c39c363af219e595eab7d4da6f7/Objects/descrobject.c#L594
Can Cython help us out here somehow?
Ok, confirming that the speed penalty for frozen slot attributes with the Cython accelerator is within 10%.
Non-frozen access: 35.3 ns +- 1.1 ns
I think this makes the idea of having some Cython code in attrs worthwhile, and when we have this infrastructure in place we might want to offer accelerated versions of other components too. I agree all Cython code should be an optimized reimplementation of Python code - native code should be strictly optional.
How do we go about this though? We can have a separate package for Cythonized components, but having a single sdist that cleanly installs even without a C compiler (and just falls back to Python versions) would be less maintenance - is it possible? We will also need to get Travis to test both versions of the code, and make wheels where we can.
Somewhat unrelated: it occured to me that for frozen dict classes, we can generate a slightly different
This is functionally identical to the way we do it now, with the cached object.setattr, right? This approach totally avoids the
@Tinche , just out of curiosity what would be the overhead of transforming all attributes that require either frozen access or have convertors and/or validators, into python
setattr(clazz, attr_name, property(fget=getter_fun, fset=setter_fun))
getter_fun = lambda self: getattr(self, private_attr_name)
Properties seem to now exist for both python 2 and 3.
I don't know how to make that consistent with the base
(relates to requirement 160)
It's not stupid, the problem is the getter is slow - it involves a pure Python method call.
The current approach is similar to