[MERGE] Use slots consistently in InventoryEntry hierarchy -- regenerated against new head. Seeking another reviewer.
Jan Hudec
bulb at ucw.cz
Thu Jun 1 20:01:37 BST 2006
On Wed, May 31, 2006 at 09:15:28 -0400, Aaron Bentley wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Jan Hudec wrote:
> > And
> > quite many operations would have to look at it anyway. So this leads me
> > to thinking that perhaps I should unify the core and non-core attributes
> > and use methods like you suggested for everything, not just the
> > proplist.
>
> This sounds like it would be slower than using slots, and possibly
> slower than normal variable access, so please benchmark if you make that
> kind of change.
I have done a bit of profiling just to see whether it's best to have a class
attribute where the corresponding instance attribute does not make sense, use
try/catch, use condition on the type etc. And these are the results on my
machine:
call_overhead: slot=0.343 dict=0.340 none=0.340
call_overhead: slot=0.341 dict=0.340 none=0.339
use_try_catch: slot=0.481 dict=0.582 none=5.319
use_getattr: slot=0.702 dict=0.809 none=1.392
use_classattr: slot=0.422 dict=0.460 none=0.414
use_property: slot=0.438 dict=0.437 none=0.864
use_if: slot=0.648 dict=0.828 none=0.581
use_hasattr: slot=0.844 dict=1.010 none=1.395
The slot, dict and none are results for accessing an attribute on following
class instances respectively:
class cNone(object):
kind = 'bad'
classattr = None
propattr = property(lambda _: None)
__slots__ = []
class cSlot(cNone):
kind = 'good'
__slots__ = ['classattr', 'notattr', 'propattr']
def __init__(self):
self.classattr = True
self.notattr = True
self.propattr = True
class cDict(cNone):
kind = 'good'
propattr = None
def __init__(self):
self.classattr = True
self.notattr = True
self.propattr = True
The call_overhead times calling just:
def call_overhead(i):
return None
so we should subtract it from the access time. And than the functions are
respectively:
def use_try_catch(i):
try:
return i.notattr
except AttributeError:
return None
You can see this is Ok if the attribute exists, but just plain appaling when
it does not.
def use_getattr(i):
return getattr(i, 'notattr', None)
The turns out to be quite dissatisfactory. That surprises me a little bit,
but I guess that it can be explained by the need to lookup getattr by name
and the fact the attribute name is not interned.
def use_classattr(i):
return i.classattr
The classattr is a classattr in the base class. As you can see, it's the
fastest in all cases.
def use_property(i):
return i.propattr
The call to lambda self: None seems to really hurt performance, so I'm going
to avoid this now and in future. Especially since when the instance does not
have __dict__, class attribute makes a good read-only attribute on the
instance.
def use_if(i):
if i.kind == 'good':
return i.notattr
else:
return None
This does two attribute accesses, so it is inevitably slower. Ok, I admit it
was a bad idea.
def use_hasattr(i):
if hasattr(i, 'notattr'):
return i.notattr
else:
return None
Although the documentation says it calls getattr and catches the exception,
it is quite significantly faster than try/catch in the bad case. I guess
given the explicit way python handles exceptions on the C level, they are
a lot easier to catch there.
Also notice, that the slots actually do a lot less difference, than the
access method used.
And that's all, folks. So I'll add class attributes into InventoryEntry for
all attributes that only apply to some of it's descendants.
I attach the measurement script as a whole if you are interested. Notice,
that there is one more measurement running for the each set, that is not
printed. That is because I found that the first run tens to give higher
results, sometimes by more than 1/3!
--
Jan 'Bulb' Hudec <bulb at ucw.cz>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ,time-access.py
Type: text/x-python
Size: 1990 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060601/c8a4efc6/attachment.py
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060601/c8a4efc6/attachment.pgp
More information about the bazaar
mailing list