#12808: Optimize ClassCallMetaClass using Cython
--------------------------------------------------+-------------------------
Reporter: hivert | Owner: jason
Type: enhancement | Status: needs_review
Priority: major | Milestone: sage-5.0
Component: misc | Resolution:
Keywords: classcall UniqueRepresentation | Work issues:
Report Upstream: N/A | Reviewers:
Authors: Florent Hivert, Simon King | Merged in:
Dependencies: | Stopgaps:
--------------------------------------------------+-------------------------
Comment (by SimonKing):
Replying to [comment:43 SimonKing]:
> But of course the time for creating (not just for calling) the instances
matters as well.
In my previous posts, I have demonstrated that some "magical" methods are
equally fast for a cdef class and for a python class that inherits from
the cdef class. See `__call__`, `__hash__` and `__add__`. I only found a
speed penalty for inherited non-magical methods.
However, the creation of instances is indeed A LOT faster for cdef classes
than for Python classes. Recall the definition of T1, ..., T4, C1, ...,
C4, Cdirect and Cindirect. We get
{{{
sage: timeit("a = T1()", number=300000)
300000 loops, best of 3: 102 ns per loop
sage: timeit("a = T2()", number=300000)
300000 loops, best of 3: 102 ns per loop
sage: timeit("a = T3()", number=300000)
300000 loops, best of 3: 102 ns per loop
sage: timeit("a = T4()", number=300000)
300000 loops, best of 3: 102 ns per loop
sage: timeit("a = C1()", number=300000)
300000 loops, best of 3: 16.9 µs per loop
sage: timeit("a = C2()", number=300000)
300000 loops, best of 3: 17 µs per loop
sage: timeit("a = C3()", number=300000)
300000 loops, best of 3: 17.2 µs per loop
sage: timeit("a = C4()", number=300000)
300000 loops, best of 3: 17 µs per loop
sage: timeit("a = Cdirect()", number=300000)
300000 loops, best of 3: 18.8 µs per loop
sage: timeit("a = Cindirect()", number=300000)
300000 loops, best of 3: 20.1 µs per loop
}}}
According to these timings, I would expect that the creation of classes
with an actual cdef metaclass (as with my second patch) is faster than the
creation of classes with a Python metaclass that inherits from a cdef
class (like `ClasscallType`). Let's test:
{{{
sage: cython("""
....: from sage.misc.classcall_metaclass import ClasscallMetaclass
....: def test_creation():
....: class A:
....: __metaclass__ = ClasscallMetaclass
....: @staticmethod
....: def __classcall__(cls, x):
....: return x
....: """)
}}}
Without patches:
{{{
sage: timeit("test_creation()", number=10000)
10000 loops, best of 3: 41.7 µs per loop
}}}
With your patch only:
{{{
sage: timeit("test_creation()", number=10000)
10000 loops, best of 3: 45.8 µs per loop
}}}
With the first two patches:
{{{
sage: timeit("test_creation()", number=10000)
10000 loops, best of 3: 38.5 µs per loop
}}}
With all three patches:
{{{
sage: timeit("test_creation()", number=10000)
10000 loops, best of 3: 38.5 µs per loop
}}}
And when cimporting the metaclass (which of course only works with all
three patches):
{{{
sage: cython("""
....: from sage.misc.classcall_metaclass cimport ClasscallMetaclass
....: def test_creation():
....: class A:
....: __metaclass__ = ClasscallMetaclass
....: @staticmethod
....: def __classcall__(cls, x):
....: return x
....: """)
sage: timeit("test_creation()", number=10000)
10000 loops, best of 3: 38.2 µs per loop
}}}
In other words: It seems that directly cdefining the metaclasses is not
only clearer than the use of `ClasscallType`, but it is indeed a little
(but not much) faster.
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/12808#comment:44>
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.