Issue 32357: Optimize asyncio.iscoroutine() and loop.create_task() for non-native coroutines (original) (raw)

asyncio.Task now uses asyncio.iscoroutine() to give a comprehensible error if a user creates a Task for a non-awaitable type.

The problem is that iscoroutine() is quite expensive for non-native coroutines (like the ones compiled with Cython), as it uses isinstance(obj, collections.abc.Coroutine) call. This makes 'loop.create_task(cython_coroutine)' 20% slower than 'loop.create_task(python_coroutine)'.

The PR adds a positive type cache to the iscoroutine() function and to the asyncio.Task C implementation. Both caches make 'loop.create_task()' equally fast for all kinds of coroutines.