Cinder de código aberto do Facebook, um fork do CPython usado pelo Instagram

O Facebook publicou o código-fonte do Projeto Cinder, um fork do CPython 3.8.5, a principal implementação de referência da linguagem de programação Python. O Cinder é usado na infraestrutura de produção do Facebook para alimentar o Instagram e inclui otimizações para melhorar o desempenho.

O código é publicado para discutir a possibilidade de portar as otimizações preparadas para o framework principal do CPython e para ajudar outros projetos envolvidos na melhoria do desempenho do CPython. O Facebook não pretende oferecer suporte ao Cinder na forma de um projeto de código aberto separado e o código é apresentado na forma em que é utilizado na infraestrutura da empresa, sem revisão e documentação adicionais. Eles também não tentam promover o Cinder como uma alternativa ao CPython - o principal objetivo do desenvolvimento é o desejo de melhorar o próprio CPython.

O código Cinder é apontado como bastante confiável e testado em ambientes de produção, mas se forem identificados problemas, você terá que resolvê-los sozinho, pois o Facebook não garante que responderá a mensagens de erro externas e pull requests. Ao mesmo tempo, o Facebook não exclui a cooperação construtiva com a comunidade e está pronto para discutir ideias sobre como tornar o Cinder ainda mais rápido ou como acelerar a transferência das alterações preparadas para a parte principal do CPython.

Principais otimizações implementadas no Cinder:

  • Cache embutido de bytecode (“bytecode sombra”). A essência do método é identificar situações em que um código de operação típico é executado e que pode ser otimizado e substituir dinamicamente esse código de operação por opções especializadas mais rápidas (por exemplo, substituindo funções chamadas com frequência).
  • Avaliação ansiosa da rotina. Para chamadas de função assíncronas que são processadas imediatamente (await não resulta em espera e a função atinge a instrução return mais cedo), o resultado de tais funções é substituído diretamente sem criar uma corrotina ou envolver um loop de eventos. No código do Facebook que usa muito async/await, a otimização resulta em uma aceleração de cerca de 5%.
  • Compilação JIT seletiva no nível de métodos e funções individuais (método por vez). Ativado por meio da opção “-X jit” ou da variável de ambiente PYTHONJIT=1 e permite acelerar a execução de muitos testes de desempenho em 1.5 a 4 vezes. Como a compilação JIT é relevante apenas para funções executadas com frequência, não é aconselhável usá-la para funções raramente usadas, cuja sobrecarga de compilação só pode retardar a execução do programa.

    Através da opção “-X jit-list-file=/path/to/jitlist.txt” ou da variável de ambiente “PYTHONJITLISTFILE=/path/to/jitlist.txt” você pode especificar um arquivo com uma lista de funções para as quais JIT pode ser usado (formato de caminho .to.module:funcname ou path.to.module:ClassName.method_name). A lista de funções para as quais o JIT deve ser habilitado pode ser determinada com base nos resultados da criação de perfil. No futuro, espera-se suporte para compilação JIT dinâmica com base na análise interna da frequência das chamadas de função, mas tendo em conta as especificidades dos processos de lançamento no Instagram, a compilação JIT também é adequada para o Facebook na fase inicial.

    JIT primeiro converte o bytecode Python em uma representação intermediária de alto nível (HIR), que é bastante próxima do bytecode Python, mas é projetada para usar uma máquina virtual baseada em registro em vez de uma baseada em pilha, e também usa informações de tipo e adicionais detalhes críticos de desempenho (como contagem de referência). O HIR é então convertido para o formato SSA (atribuição única estática) e passa por etapas de otimização que levam em consideração resultados de contagem de referência e dados de consumo de memória. Como resultado, é gerada uma representação intermediária de baixo nível (LIR), próxima à linguagem assembly. Após outra fase de otimizações baseadas em LIR, as instruções de montagem são geradas usando a biblioteca asmjit.

  • Modo estrito para módulos. A funcionalidade inclui três componentes: Tipo StrictModule. Um analisador estático que pode determinar que a execução de um módulo não tem impacto no código fora desse módulo. Um carregador de módulo que determina se os módulos estão no modo estrito (o código especifica “import __strict__”), verifica a ausência de interseções com outros módulos e carrega módulos estritos em sys.modules como um objeto StrictModule.
  • Static Python é um compilador de bytecode experimental que usa anotações de tipo para gerar bytecode específico do tipo que é executado mais rapidamente graças à compilação JIT. Em alguns testes, a combinação de Static Python e JIT demonstra melhorias de desempenho de até 7 vezes em comparação ao CPython padrão. Em muitas situações, estima-se que os resultados sejam próximos ao uso dos compiladores MyPyC e Cython.

Fonte: opennet.ru

Adicionar um comentário