diff options
author | da-woods <dw-git@d-woods.co.uk> | 2023-03-21 18:07:42 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-21 18:07:42 +0000 |
commit | 10aa1bf6821398c8d0e881e5348c2930df6d0b04 (patch) | |
tree | 8b2fdd338c4298c4426692a911f74d4758fe571c | |
parent | 65b26bca80498209ff77fd87831c7407f81e5340 (diff) | |
download | cython-10aa1bf6821398c8d0e881e5348c2930df6d0b04.tar.gz |
Document the nongil except* performance pitfall (#5327)
-rw-r--r-- | docs/src/userguide/language_basics.rst | 9 | ||||
-rw-r--r-- | docs/src/userguide/migrating_to_cy30.rst | 10 |
2 files changed, 19 insertions, 0 deletions
diff --git a/docs/src/userguide/language_basics.rst b/docs/src/userguide/language_basics.rst index 7a057b4fb..41a7b9392 100644 --- a/docs/src/userguide/language_basics.rst +++ b/docs/src/userguide/language_basics.rst @@ -930,6 +930,15 @@ Some things to note: which return Python objects. Remember that a function with no declared return type implicitly returns a Python object. (Exceptions on such functions are implicitly propagated by returning ``NULL``.) + +* There's a known performance pitfall when combining ``nogil`` and + ``except *`` \ ``@cython.exceptval(check=True)``. + In this case Cython must always briefly re-acquire the GIL after a function + call to check if an exception has been raised. This can commonly happen with a + function returning nothing (C ``void``). Simple workarounds are to mark the + function as ``noexcept`` if you're certain that exceptions cannot be thrown, or + to change the return type to ``int`` and just let Cython use the return value + as an error flag (by default, ``-1`` triggers the exception check). .. _checking_return_values_of_non_cython_functions: diff --git a/docs/src/userguide/migrating_to_cy30.rst b/docs/src/userguide/migrating_to_cy30.rst index f4bc32f39..1330fd12b 100644 --- a/docs/src/userguide/migrating_to_cy30.rst +++ b/docs/src/userguide/migrating_to_cy30.rst @@ -210,6 +210,16 @@ The behaviour for any ``cdef`` function that is declared with an explicit exception value (e.g., ``cdef int spam(int x) except -1``) is also unchanged. +There's an easy-to-encounter performance pitfall here with ``nogil`` functions +with an implicit exception specification of ``except *``. This can happen +most commonly when the return type is ``void`` (but in principle applies +to most non-numeric return types). In this case, Cython is forced to +re-acquire the GIL briefly after each call to check the exception state. +To avoid this overhead, either change the signature to ``noexcept`` (if +you have determined that it's suitable to do so), or to return a ``int`` +instead to let Cython use the ``int`` as an error flag +(by default, ``-1`` triggers the exception check). + .. note:: The unsafe legacy behaviour of not propagating exceptions by default can be enabled by setting ``legacy_implicit_noexcept`` :ref:`compiler directive<compiler-directives>` |