[PATCH 1 of 8] perf: introduce safeattrsetter to replace direct attribute assignment

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Mon Aug 8 10:59:39 EDT 2016


At Mon, 8 Aug 2016 23:20:04 +0900,
Yuya Nishihara wrote:
> 
> On Mon, 08 Aug 2016 18:59:40 +0900, FUJIWARA Katsunori wrote:
> > # HG changeset patch
> > # User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
> > # Date 1470649697 -32400
> > #      Mon Aug 08 18:48:17 2016 +0900
> > # Node ID e5f93a8eb06c9b189c4f2460a66fe8f2d7713655
> > # Parent  84a8de5ac901c00f4efec1ec2e0be24ebd970fd8
> > perf: introduce safeattrsetter to replace direct attribute assignment
> 
> > To avoid examining existence of attribute at each repetition, this
> > patch makes safeattrsetter() return the function, which actually
> > assigns a value to an attribute.
> 
> [snip]
> 
> > +def safeattrsetter(obj, name, ignoremissing=False):
> > +    """Ensure that 'obj' has 'name' attribute before execution of setattr
> > +
> > +    This function is aborted, if 'obj' doesn't have 'name' attribute
> > +    at runtime. This avoids overlooking removal of an attribute, which
> > +    breaks assumption of performance measurement, in the future.
> > +
> > +    This function returns the function to assign a value to 'name'
> > +    attribute. This "setter" function returns the function to restore
> > +    'name' attribute to old one.
> > +
> > +    If 'ignoremissing' is true, missing 'name' attribute doesn't cause
> > +    abortion, and this function returns None. This is useful to
> > +    examine an attribute, which isn't ensured in all Mercurial
> > +    versions.
> > +    """
> > +    if not util.safehasattr(obj, name):
> > +        if ignoremissing:
> > +            return None
> > +        raise error.Abort(("missing attribute %s of %s might break assumption"
> > +                           " of performance measurement") % (name, obj))
> > +
> > +    def setter(newvalue):
> > +        oldvalue = getattr(obj, name)
> 
> If you care for the cost of safehasattr() (that could load a propertycache?),
> getattr() should be removed from the perf loop as well.
> 
> > +        setattr(obj, name, newvalue)
> > +        def restorer():
> > +            setattr(obj, name, oldvalue)
> > +        return restorer
> 
> Maybe this could be a class to avoid long closure chain.
> 
>   s = safeattrsetter(obj, name)  # remember current obj.name (=v0)
>   s.set(v1)
>   s.set(v2)
>   s.restore()  # restore v0, not v1

That looks better. I'll post revised one, thank you.

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy at lares.dti.ne.jp


More information about the Mercurial-devel mailing list