Cinder de código abierto de Facebook, una bifurcación de CPython utilizada por Instagram

Facebook ha publicado el código fuente de Project Cinder, un fork de CPython 3.8.5, la principal implementación de referencia del lenguaje de programación Python. Cinder se utiliza en la infraestructura de producción de Facebook para impulsar Instagram e incluye optimizaciones para mejorar el rendimiento.

El código se publica para discutir la posibilidad de portar las optimizaciones preparadas al marco principal de CPython y para ayudar a otros proyectos involucrados en mejorar el rendimiento de CPython. Facebook no tiene la intención de apoyar a Cinder como un proyecto de código abierto separado y el código se presenta en la forma en que se utiliza en la infraestructura de la empresa, sin análisis ni documentación adicional. Tampoco intentan promover a Cinder como una alternativa a CPython; el objetivo principal del desarrollo es el deseo de mejorar el propio CPython.

El código de Cinder se considera bastante confiable y probado en entornos de producción, pero si se identifican problemas, tendrá que resolverlos usted mismo, ya que Facebook no garantiza que responderá a mensajes de error externos y solicitudes de extracción. Al mismo tiempo, Facebook no excluye la cooperación constructiva con la comunidad y está dispuesto a discutir ideas sobre cómo hacer que Cinder sea aún más rápido o cómo acelerar la transferencia de los cambios preparados a la parte principal de CPython.

Principales optimizaciones implementadas en Cinder:

  • Almacenamiento en caché en línea de código de bytes (“código de bytes oculto”). La esencia del método es identificar situaciones en las que se ejecuta un código de operación típico que se puede optimizar y reemplazar dinámicamente dicho código de operación con opciones especializadas más rápidas (por ejemplo, reemplazar funciones llamadas con frecuencia).
  • Evaluación de rutina ansiosa. Para las llamadas a funciones asíncronas que se procesan inmediatamente (await no da como resultado una espera y la función llega antes a la declaración de retorno), el resultado de dichas funciones se sustituye directamente sin crear una rutina ni involucrar un bucle de eventos. En el código de Facebook que utiliza mucho async/await, la optimización da como resultado una aceleración de aproximadamente el 5%.
  • Compilación JIT selectiva a nivel de métodos y funciones individuales (método a la vez). Se habilita mediante la opción "-X jit" o la variable de entorno PYTHONJIT=1 y le permite acelerar la ejecución de muchas pruebas de rendimiento entre 1.5 y 4 veces. Dado que la compilación JIT sólo es relevante para funciones ejecutadas con frecuencia, no es aconsejable utilizarla para funciones que se utilizan con poca frecuencia, cuya sobrecarga de compilación sólo puede ralentizar la ejecución del programa.

    A través de la opción “-X jit-list-file=/path/to/jitlist.txt” o la variable de entorno “PYTHONJITLISTFILE=/path/to/jitlist.txt” puede especificar un archivo con una lista de funciones para las cuales JIT se puede utilizar (formato de ruta .to.module:funcname o ruta.to.module:ClassName.method_name). La lista de funciones para las que se debe habilitar JIT se puede determinar en función de los resultados del perfil. En el futuro, se espera soporte para la compilación JIT dinámica según el análisis interno de la frecuencia de las llamadas a funciones, pero teniendo en cuenta las características específicas de los procesos de inicio en Instagram, la compilación JIT también es adecuada para Facebook en la etapa inicial.

    JIT primero convierte el código de bytes de Python en una representación intermedia de alto nivel (HIR), que es bastante similar al código de bytes de Python, pero está diseñado para usar una máquina virtual basada en registros en lugar de una basada en pilas, y también usa información de tipo y datos adicionales. Detalles críticos para el rendimiento (como el recuento de referencias). Luego, el HIR se convierte al formato SSA (asignación única estática) y pasa por pasos de optimización que tienen en cuenta los resultados del recuento de referencias y los datos de consumo de memoria. Como resultado, se genera una representación intermedia de bajo nivel (LIR), cercana al lenguaje ensamblador. Después de otra fase de optimizaciones basadas en LIR, las instrucciones de ensamblaje se generan utilizando la biblioteca asmjit.

  • Modo estricto para módulos. La funcionalidad incluye tres componentes: Escriba StrictModule. Un analizador estático que puede determinar que la ejecución de un módulo no tiene impacto en el código fuera de ese módulo. Un cargador de módulos que determina que los módulos están en modo estricto (el código especifica "importar __strict__"), verifica la ausencia de intersecciones con otros módulos y carga módulos estrictos en sys.modules como un objeto StrictModule.
  • Static Python es un compilador de código de bytes experimental que utiliza anotaciones de tipo para generar código de bytes de tipo específico que se ejecuta más rápido gracias a la compilación JIT. En algunas pruebas, la combinación de Static Python y JIT demuestra mejoras de rendimiento de hasta 7 veces en comparación con CPython estándar. En muchas situaciones, se estima que los resultados se aproximan a los del uso de los compiladores MyPyC y Cython.

Fuente: opennet.ru

Añadir un comentario