New submission from Vladimir Matveev <desco...@gmail.com>:

Currently async functions are more expensive to use comparing to their sync 
counterparts. A simple microbenchmark shows that difference could be quite 
significant:
```
import time

def f(a):
    if a == 0:
        return 0
    return f(a - 1)

async def g(a):
    if a == 0:
        return 0
    return await g(a - 1)

N = 100000
C = 200

t0 = time.time()
for _ in range(N):
    f(C)
t1 = time.time()
for _ in range(N):
    try:
        g(C).send(None)
    except StopIteration:
        pass
t2 = time.time()

print(f"Sync functions: {t1 - t0} s")
print(f"Coroutines: {t2 - t1} s")
```
Results from master on my machine:

Sync functions: 2.8642687797546387 s
Coroutines: 9.172159910202026 s

NOTE: Due to viral nature of async functions their number in codebase could 
become quite significant so having hundreds of them in a single call stack is 
not something uncommon.

One of reasons of such performance gap is that async functions always return 
its results via raising StopIteration exception which is not cheap. This can be 
avoided if in addition to `_PyGen_Send` always return result via exception we 
could have another function that will allow us to distinguish whether value 
that was returned from generator is a final result (return case) of whether 
this is yielded value.
In linked PR I've added function `_PyGen_SendNoStopIteration` with this 
behavior and updated ceval.c and _asynciomodule.c to use it instead of 
`_PyGen_Send` which resulted in a measurable difference:

Sync functions: 2.8861589431762695 s
Coroutines: 5.730362176895142 s

----------
messages: 376698
nosy: v2m, yselivanov
priority: normal
severity: normal
status: open
title: Do not always use exceptions to return result from coroutine
type: performance
versions: Python 3.10

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue41756>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to