Make is_awaitable faster for values that are not awaitable

Aperta Adatta ai principianti
#308 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@dexhunter ci sta già lavorando.

Dal 7/11/2026.

  • #309 di @dexhunter — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
python

Direzione di ricerca

Inizia individuando is_awaitable nel codice sorgente di graphql-core e leggi i punti in cui viene chiamato e i test esistenti per coroutine, coroutine basate su generatori, futures e oggetti che espongono __await__. Riproduci il benchmark con tests/benchmarks/test_async_iterable.py usando il comando indicato nell’issue, quindi confronta il comportamento e i tempi dopo la modifica proposta all’ordine dei controlli. Il lavoro è completato quando i risultati awaitable e gli errori elencati vengono mantenuti e il caso non-awaitable migliora.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

is_awaitable runs up to three checks for every value.
For a plain value such as an int or a str, it always runs all three.
The executor calls it for every resolved and completed item, so a list of 1,000 items runs it about 2,000 times.

The CoroutineType test does not change the result.
Every coroutine object has an __await__ attribute, so the hasattr check also finds it.
Generator-based coroutines (types.coroutine) have no __await__, so they still need the code-flag check.

A local change removes the CoroutineType test.
It checks the exact generator type first and then checks for __await__.

Situation Before After Change
test_execute_async_iterable_list_field (median) 1.183 ms 1.115 ms 5.8% less time
Sync list field with 1,000 items 1.019 ms 0.927 ms 9.0% less time
1,000 async field resolvers (coroutines) 7.75 ms 7.83 ms Within variation: 1.0% more time
is_awaitable(1) 102.9 ns 66.0 ns 35.9% less time
is_awaitable(coroutine) 54.0 ns 87.8 ns 62.6% more time

The coroutine call itself is slower, because hasattr costs more than isinstance.
In a full query this cost stays inside normal variation, because awaiting the coroutine costs much more.

The results are the same for coroutines, generator-based coroutines, futures, and objects with __await__ on the instance, via __getattr__, or via a property.
Errors from a raising __getattr__ or property stay the same.

Environment: CPython 3.12.13, Linux x86-64, one dedicated CPU core.
Base commit: 1d505c19bf5fb8da0205165b78af6094d637009e.

Reproduce on the base and changed versions:

PYTHONPATH=src python -m pytest tests/benchmarks/test_async_iterable.py --benchmark-enable --benchmark-min-rounds=1000
Lingua principale
Python
Stelle
534
Fork
159
Merge medio
1g 18h
PR unite (30g)
9

Preparare l'ambiente

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di graphql-python/graphql-core

Tutte le issue di graphql-python/graphql-core

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.