Make is_awaitable faster for values that are not awaitable

Ouverte Adaptée aux débutants
#308 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@dexhunter y travaille déjà.

Depuis le 7/11/2026.

  • #309 par @dexhunter — ouverte

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
72/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
Active
Stack technique
python

Piste de recherche

Commencez par localiser is_awaitable dans le code source de graphql-core et lisez ses appelants ainsi que les tests existants pour les coroutines, les coroutines basées sur des générateurs, les futures et les objets exposant __await__. Reproduisez le benchmark avec tests/benchmarks/test_async_iterable.py à l’aide de la commande indiquée dans l’issue, puis comparez le comportement et le temps d’exécution après la modification proposée de l’ordre des vérifications. Le travail est terminé si les résultats et les erreurs awaitable répertoriés sont préservés, tout en améliorant le cas non-awaitable.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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
Langage dominant
Python
Étoiles
534
Forks
159
Merge moyen
1 j 18 h
PR mergées (30 j)
9

Préparer son environnement

  • Aucun Dockerfile ni fichier Docker Compose
  • Propose un modèle de pull request
  • Aucun guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de graphql-python/graphql-core

Toutes les issues de graphql-python/graphql-core

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.