Make is_awaitable faster for values that are not awaitable

Aberta Para iniciantes
#308 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

@dexhunter já está trabalhando nisso.

Desde 7/11/2026.

  • #309 de @dexhunter — aberto

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
72/100
Tipo de issue
Bug
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
python

Direção de pesquisa

Comece localizando is_awaitable no código-fonte do graphql-core e leia os pontos em que é chamado e os testes existentes para corrotinas, corrotinas baseadas em geradores, futures e objetos que expõem __await__. Reproduza o benchmark com tests/benchmarks/test_async_iterable.py usando o comando indicado na issue e, em seguida, compare o comportamento e o tempo de execução após a mudança proposta na ordem das verificações. O trabalho estará concluído quando os resultados awaitable e os erros listados forem preservados e o caso não awaitable melhorar.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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
Linguagem predominante
Python
Estrelas
534
Forks
159
Merge médio
1d 18h
PRs com merge (30d)
9

Preparar o ambiente

  • Sem Dockerfile nem arquivo Docker Compose
  • Tem um modelo de pull request
  • Sem guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de graphql-python/graphql-core

Todas as issues de graphql-python/graphql-core

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.