La ventaja de esto es que esto reduce la barrera de contribución. En algunos casos, reduce los costos de callback de C++ a JavaScript. Pero al mismo tiempo, esto hace que sea más difícil mantener el rendimiento de inicio. Por un lado, el código de JavaScript necesita ser analizado y compilado antes de que pueda ser ejecutado, y eso lleva tiempo. Además, la mayoría del código de JavaScript para la inicialización sólo se ejecuta una vez durante el inicio porque es sólo inicialización, por lo que no se optimiza por el motor de JavaScript.
Al implementar una biblioteca en JavaScript, tenemos que tener en cuenta la posible contaminación del prototipo. No quieres que el usuario haga explotar el tiempo de ejecución sólo porque borran algo del edificio a un prototipo, como el prototipo de cadena que comenzó con. Así que para mitigar esto, no necesitamos crear copias de estos edificios de JavaScript como inicio para el uso interno. En realidad no utilizan los métodos de prototipo que exponemos a los usuarios. Todo esto puede ralentizar el inicio a medida que crece el nodo.
Así que para mantener el costo de la inicialización de inicio bajo control, el núcleo de Node utiliza múltiples estrategias. Primero, no inicializamos todos los globales y edificios como inicio. Para las características que aún son experimentales o demasiado nuevas para ser utilizadas ampliamente o sólo sirven a un tipo específico de aplicación, sólo instalamos accesorios que los cargarán de forma perezosa cuando el usuario los acceda por primera vez. Y segundo, cuando construimos lanzamientos, precompilamos todos los módulos internos para generar el código de caché que contiene bytecode y metadatos, y los añadimos al ejecutable para que cuando tengamos que cargar módulos adicionales, una solicitud de usuario, pasamos el código de caché a V8, y V8 puede saltarse el análisis y la compilación, y simplemente usar el código serializado cuando se actualiza, cuando valida esa caché. Y finalmente, para las características esenciales que casi siempre tenemos que cargar, por ejemplo, la API de URL web, el módulo FS, que también es utilizado por otros internos, o como características ampliamente utilizadas como temporizadores, como tiempo, características ampliamente utilizadas como temporizadores, los capturamos en una instantánea de inicio de V8, lo que ayuda a simplemente saltar la ejecución del código de inicialización y ahorrar tiempo durante el inicio.
Así que esto es algo así como cómo solía ser construido y ejecutado el ejecutable de nodo. Inicialmente, sólo estábamos incrustando el código de JavaScript en el ejecutable, en tiempo de construcción. Y en tiempo de ejecución, necesitamos analizarlo, necesitamos compilarlo, necesitamos ejecutarlo para obtener el núcleo de nodo inicializado, y antes de que podamos ejecutar el código del usuario y procesar los estados del sistema para inicializar la aplicación del usuario. Y luego introdujimos la caché de código incrustada. Así que en tiempo de construcción, precompilamos todo el código de JavaScript interno y generamos la caché de código compilado, y luego los incrustamos en el ejecutable. Y en tiempo de ejecución, le pediremos a VA que use la caché de código y salte el proceso de análisis y compilación. Todavía mantendremos el código de JavaScript interno como la fuente de verdad, en caso de que la caché de código no se valide en el entorno de ejecución actual, pero la mayoría de las veces, el código se utiliza, y simplemente saltamos el proceso de compilación. Y ahora, con la integración de la instantánea de inicio, simplemente ejecutamos el código de JavaScript interno en tiempo de construcción para inicializar un montón de notas y luego capturamos una instantánea y la incrustamos en el ejecutable. Los otros dos todavía se mantienen como respaldo, pero en tiempo de ejecución simplemente deserializamos la instantánea para obtener el montón inicializado. Así que no hay necesidad de analizar, compilar, ejecutar. El código interno es simplemente como, deserializas el resultado. Entonces, ¿qué son exactamente estas instantáneas de inicio de VA? Básicamente son el montón de VA serializado en un blob binario. Hay dos capas de instantáneas, una que captura todos los primitivos y las vinculaciones nativas, y una que captura los contactos de ejecución, como los objetos y funciones. Así que actualmente, NOE utiliza la instantánea de aislamiento para todos los aislamientos que puedes crear desde la tierra de los usuarios, incluyendo el aislamiento principal y los aislamientos de los trabajadores. También tenemos instantáneas de contactos incorporadas para los contactos principales, los contactos VM, y los contactos de los trabajadores, aunque la instantánea de los contactos de los trabajadores actualmente sólo contiene cosas muy mínimas.
Comments