Search code examples
cython

Performance benefits of using @cython.final in cdef class?


I'm currently reading about the @cython.final decorator, and I'm wondering whether it adds any performance benefits at runtime or only prevents certain actions throwing errors as documented in https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html

Thanks,


Solution

  • I'm wondering whether it adds any performance benefits at runtime

    Yes.

    The main advantage is when calling cdef/cpdef functions. Consider:

    cdef class C:
        cdef f(self):
            ...
    
    def some_func(C c):
        c.f()
    

    without final this would call either C.f or an overridden function in any derived class. This call looks like:

    ((struct __pyx_vtabstruct_3fnl_C *)__pyx_v_c->__pyx_vtab)->f(__pyx_v_c); 
    

    (i.e. it goes through a "vtable" and two pointer-dereferences to work out the actual function called.)

    With final the call looks like

    __pyx_f_3fnl_1C_f(__pyx_v_c)
    

    (i.e. it knows the exact function at compile-time and goes through no pointer-dereferences).

    With cpdef the difference is even more dramatic because cpdef functions may be overridden by derived classes implemented in Python, so the check involves a dict lookup too.

    There's also some other optimizations:

    • Allocation/deallocation of final classes. Again, steps can be skipped because the exact class being allocated is known at compile time.
    • Attribute lookup - we know at compile-time if the class has a __dict__ for each instance.

    The optimization of method calls is the main one (and is fairly general and will apply to most languages with have the concept of a "final" type).