summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2023-03-21 18:07:42 +0000
committerGitHub <noreply@github.com>2023-03-21 18:07:42 +0000
commit10aa1bf6821398c8d0e881e5348c2930df6d0b04 (patch)
tree8b2fdd338c4298c4426692a911f74d4758fe571c
parent65b26bca80498209ff77fd87831c7407f81e5340 (diff)
downloadcython-10aa1bf6821398c8d0e881e5348c2930df6d0b04.tar.gz
Document the nongil except* performance pitfall (#5327)
-rw-r--r--docs/src/userguide/language_basics.rst9
-rw-r--r--docs/src/userguide/migrating_to_cy30.rst10
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>`