#10467: Improve lookup of private attributes
---------------------------+------------------------------------------------
Reporter: SimonKing | Owner: tbd
Type: enhancement | Status: new
Priority: major | Milestone: sage-4.6.1
Component: performance | Keywords: private attribute lookup
Author: Simon King | Upstream: N/A
Reviewer: | Merged:
Work_issues: |
---------------------------+------------------------------------------------
By a private attribute, I mean an attribute whose name starts with two
underscores and does not end with an underscore. Such an attribute is
used, e.g., in the default `__repr__` method of Sage objects.
It should be reasonable to assume that private attributes belong to a
particular instance, not to its class or its category. In particular, if
`P` is a parent/element, then `P.__foo` is either defined for the instance
`P` or will not be available from `P.category().parent_class` resp. from
`P.category().element_class`.
It turns out that this assumption holds thorought Sage: When one lets the
`__getattr__` methods of Parent/Element immediately raise an
`AttributeError` when a private attribute is requested, then all doc tests
still pass.
That is what my patch mainly does. In addition, it removes several
occurences of an idiom like
{{{
if hasattr(self,'foo'):
return self.foo
}}}
and replaces it with
{{{
try:
return self.foo
except AttributeError:
pass
}}}
which saves half of the computation time when the attribute actually
exists.
The advantage is a considerable speedup. Here are two examples (the last
is actually a serious computation):
Without the patch:
{{{
sage: P.<x> = QQ[]
sage: timeit('a=repr(x)')
625 loops, best of 3: 74.7 µs per loop
sage: R.<x,y> = InfinitePolynomialRing(QQ)
sage: I = R.ideal([x[1]^2+y[2]*y[3], x[2]*y[1]*x[3]-y[1]*y[2]])
sage: %time I.groebner_basis()
CPU times: user 23.09 s, sys: 0.02 s, total: 23.11 s
Wall time: 23.67 s
[y_2*y_1^3 + y_2*y_1^2, y_2^2*y_1 - y_2*y_1^2, y_3*y_1 - y_2*y_1,
x_1*y_2*y_1^2 + x_1*y_2*y_1, x_1^2 + y_2*y_1, x_2*y_2*y_1 - x_1*y_2*y_1,
x_2*x_1*y_3 - y_2*y_1, x_3*y_2*y_1 - x_1*y_2*y_1, x_3*x_1*y_2 - y_2*y_1,
x_3*x_2*y_1 - y_2*y_1]
}}}
With the patch:
{{{
sage: P.<x> = QQ[]
sage: timeit('a=repr(x)')
625 loops, best of 3: 40.5 µs per loop
sage: R.<x,y> = InfinitePolynomialRing(QQ)
sage: I = R.ideal([x[1]^2+y[2]*y[3], x[2]*y[1]*x[3]-y[1]*y[2]])
sage: %time I.groebner_basis()
CPU times: user 14.43 s, sys: 0.03 s, total: 14.46 s
Wall time: 14.53 s
[y_2*y_1^3 + y_2*y_1^2, y_2^2*y_1 - y_2*y_1^2, y_3*y_1 - y_2*y_1,
x_1*y_2*y_1^2 + x_1*y_2*y_1, x_1^2 + y_2*y_1, x_2*y_2*y_1 - x_1*y_2*y_1,
x_2*x_1*y_3 - y_2*y_1, x_3*y_2*y_1 - x_1*y_2*y_1, x_3*x_1*y_2 - y_2*y_1,
x_3*x_2*y_1 - y_2*y_1]
}}}
The patch also adds doctests in `Parent.__getattr__`,
`Element.__getattr__` and several methods of `SageObject`.
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/10467>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en.