Quantas linhas de C são necessárias para executar um + b em Python

A expressão simples `a + b` em Python esconde uma grande quantidade de código em C e maquinaria de runtime, desde dispatch dinâmico e métodos mágicos até inteiros de precisão arbitrária e busca de atributos baseada em hash. Os comentaristas usam isso como ponto de partida para examinar por que o CPython é relativamente lento em comparação com runtimes baseados em JIT (como V8, LuaJIT ou PyPy), apontando escolhas de design como dinamismo onipresente de objetos, a API C e hashing orientado à segurança. Muitos argumentam que o Python se destaca como “cola” em torno de bibliotecas rápidas em C ou C++, em vez de como um motor de computação de alto desempenho, e que ganhos substanciais de velocidade exigiriam mudanças arquitetônicas profundas, não apenas ajustes superficiais.

Escopo da pergunta original

  • Muitos observam que o artigo na verdade não responde “quantas linhas de C” são executadas para a + b.
  • Vários argumentam que a noção é mal formulada: uma vez que você permite sobrecarga de operador (__add__/__radd__), a + b pode realizar trabalho arbitrariamente complexo.
  • Outros sugerem que, no mínimo, seria possível medir uma execução concreta usando cobertura de código ou profiling, mas mesmo isso depende do caminho seguido e da entrada.

Dispatch dinâmico, métodos mágicos e complexidade

  • A discussão enfatiza quanta maquinaria existe por trás até das operações mais simples no CPython: modelo de objetos, dispatch dinâmico via slots de tipo, métodos mágicos __dunder__, descriptors e exceções para iteração.
  • Comparado a linguagens como JS ou Lua, o Python expõe “mágica” de forma mais abrangente em objetos comuns, o que torna mais difícil fazer otimizações agressivas e JITing.
  • Subclassificar builtins (por exemplo, int) e descriptors personalizados complicam ainda mais a especialização.

Desempenho, JITs e trade-offs de design

  • Vários comentaristas argumentam que o CPython não é intencionalmente focado em desempenho; ele otimiza para simplicidade e interoperabilidade com C, e o Python é melhor visto como “cola” sobre bibliotecas nativas rápidas.
  • Outros contrapõem que outras linguagens dinâmicas (JS, LuaJIT, Smalltalk, JITs de Ruby) mostram que alto desempenho é possível com engenharia suficiente.
  • Há debate sobre se o design da linguagem Python ou a API C e o ecossistema são os principais obstáculos para um JIT de primeira linha.
  • Trabalhos recentes para tornar o CPython mais rápido e JITs externos (PyPy, Pyston) são mencionados; as melhorias até agora são vistas como reais, mas modestas em comparação com a revolução dos JITs em JS.

Hashing, segurança e velocidade

  • Um fio lateral revisita alegações de que mudar a função de hash do Python poderia dobrar o desempenho.
  • Vários comentaristas contestam isso: hashes de strings são armazenados em cache, nomes de símbolos são internados, e benchmarks que mostravam ganhos enormes foram criticados como irreais.
  • O SipHash aleatorizado do Python (em vez do antigo FNV) existe principalmente para resistência a HashDoS; o impacto no desempenho em workloads reais parece pequeno.
  • Discute-se o hashing por identidade para inteiros; ele interage com a implementação de tabelas de hash e pode causar patologias com certas distribuições de inteiros.

Ergonomia de C vs Python e “é só usar C”

  • Alguns sugerem que pode ser “mais fácil” usar C diretamente, mas outros ressaltam o boilerplate drasticamente menor do Python e o suporte embutido a inteiros de precisão arbitrária.
  • Exemplos destacam quantas poucas linhas de Python implementam aritmética de precisão arbitrária em comparação com as muitas linhas de C ou C++ necessárias para igualar comportamento e segurança.