Video Summary and Transcription
La capacidad de respuesta rápida es esencial, y LLRT es un nuevo tiempo de ejecución de JavaScript optimizado para entornos serverless que ofrece un rendimiento mejorado y ahorro de costos en comparación con otros tiempos de ejecución. LLRT logra un rendimiento rápido al eliminar complejidades, aprovechar Rust y optimizar el AWS SDK para Lambda. Se inicia casi seis veces más rápido que Node.js y proporciona un ahorro de costos de 2.9 veces y un ahorro de tiempo de 3.7 veces en comparación con Node.js.
1. Introducción a LLRT
La capacidad de respuesta rápida es esencial. Los servicios sin servidor como AWS Lambda a veces introducen latencia. LLRT es un nuevo tiempo de ejecución de JavaScript específicamente diseñado para entornos sin servidor. LLRT no incorpora un compilador justo a tiempo, lo que conserva los recursos de CPU y memoria. LLRT ofrece prácticamente inicios en frío despreciables y admite ECMAScript 2020 con muchas API de Node.js.
Hola a todos. En el mundo actual de las aplicaciones modernas, la capacidad de respuesta rápida es esencial. Los desarrolladores esperan una experiencia excelente en la que cada acción desencadene una respuesta inmediata.
Los servicios sin servidor como AWS Lambda permiten a los desarrolladores construir aplicaciones modernas sin la necesidad de aprovisionar servidores o infraestructura adicional. Sin embargo, estos servicios a veces introducen o agregan un poco de latencia al aprovisionar un nuevo entorno de ejecución para ejecutar el código del cliente. A esto a veces se le llama inicio en frío. Y aunque las métricas de producción muestran que los inicios en frío generalmente ocurren en menos del 1% de todas las invocaciones, y a veces incluso menos, aún puede ser un poco destructivo para la experiencia de usuario fluida que estamos buscando.
¿Qué tal si les dijera que hay una solución para los inicios en frío? ¿Qué tal si les dijera que pueden ejecutar aplicaciones de JavaScript en AWS Lambda con prácticamente inicios en frío despreciables? Mi nombre es Richard Davison. Trabajo como arquitecto de soluciones asociado, ayudando a los socios a modernizar sus aplicaciones en AWS utilizando tecnologías sin servidor y de contenedores. Y estoy aquí para hablar sobre el proyecto que he estado construyendo durante algún tiempo llamado LLRT y cómo redefine la latencia sin servidor.
Entonces, LLRT es la abreviatura de Tiempo de Ejecución de Baja Latencia. Y es un nuevo tiempo de ejecución de JavaScript construido desde cero para abordar la creciente demanda de aplicaciones sin servidor rápidas y eficientes. ¿Por qué deberíamos construir un nuevo tiempo de ejecución de JavaScript? Entonces, JavaScript es una de las formas más populares de construir y ejecutar aplicaciones sin servidor. También a menudo ofrece consistencia de pila completa, lo que significa que la backend y la frontend de su aplicación pueden compartir un lenguaje unificado, lo cual es una ventaja adicional. JavaScript también ofrece un ecosistema de paquetes rico y una gran comunidad que puede ayudar a acelerar el desarrollo de sus aplicaciones. Además, JavaScript es reconocido por ser bastante amigable para el usuario, lo que hace que sea fácil de aprender, fácil de leer y fácil de escribir. También es un estándar abierto conocido como ECMAScript, que ha sido implementado por diferentes motores, lo cual es algo de lo que hablaremos más adelante en esta presentación.
Entonces, ¿cómo es LLRT diferente de Node, Ebbun y Ordino? ¿Qué justifica la introducción de otro tiempo de ejecución de JavaScript a la luz de estas alternativas existentes? Entonces, Node, Ebbun y Ordino, representan tiempos de ejecución de JavaScript altamente competentes. Son extremadamente capaces y tienen un rendimiento muy bueno. Sin embargo, están diseñados pensando en aplicaciones de propósito general. Y estos tiempos de ejecución no fueron diseñados específicamente para las demandas de los entornos sin servidor, que a menudo se caracterizan por instancias de tiempo de ejecución de corta duración con recursos limitados. También dependen de un compilador justo a tiempo, un componente tecnológico muy sofisticado que permite compilar y optimizar dinámicamente el código de JavaScript durante la ejecución. Y aunque un compilador justo a tiempo ofrece ventajas de rendimiento sustanciales a largo plazo, a menudo conlleva una sobrecarga computacional y de memoria, especialmente cuando se hace con recursos limitados. En contraste, LLRT se distingue por no incorporar un compilador justo a tiempo, lo cual es una decisión estratégica que ofrece dos ventajas significativas. La primera es que, nuevamente, un compilador justo a tiempo es un componente tecnológico notablemente sofisticado que introduce una mayor complejidad del sistema y contribuye sustancialmente al tamaño del tiempo de ejecución en general. Y sin la sobrecarga de un JIT, LLRT conserva tanto los recursos de CPU como de memoria que se pueden asignar de manera más efectiva para ejecutar el código que se ejecuta dentro de su función de Lambda, y así reducir los tiempos de inicio de la aplicación. Entonces, nuevamente, un compilador justo a tiempo ofrecería un aumento de rendimiento sustancial a largo plazo, mientras que la falta de un compilador justo a tiempo puede ofrecer beneficios de inicio. LLRT está construido desde cero con un enfoque principal, el rendimiento en AWS Lambda. Por lo tanto, tiene prácticamente inicios en frío despreciables, y la duración del inicio en frío es inferior a 100 milisegundos para muchos casos de uso y tareas, incluso al realizar llamadas a la versión 3 del SDK de AWS. Utiliza un estándar bastante reciente de ECMAScript, ECMAScript 2020, con muchas API de Node.js.
2. LLRT Performance
LLRT es un tiempo de ejecución de JavaScript que ofrece un rendimiento mejorado y ahorro de costos en comparación con otros tiempos de ejecución. Utiliza un motor ligero llamado QuickJS, que tiene menos de un megabyte de tamaño. LLRT está construido en Rust y cumple con la especificación de Node.js. En una demostración, LLRT tuvo un rendimiento significativamente más rápido y consumió menos memoria en comparación con Node.js.
Y el objetivo de esto es hacer que sea una migración lo más simple posible desde Node. Viene con lo que llamamos baterías incluidas. Entonces LLRT y el binario en sí mismo ya tienen algunos SDK de AWS v3 incorporados, por lo que no es necesario enviar y proporcionar esos, lo que también tiene beneficios de rendimiento. Y hablando de beneficios de rendimiento, también hay un beneficio de costos. Y un rendimiento más estable, principalmente debido a la falta de un compilador justo a tiempo, puede llevar a una mejora de hasta 2 veces en el rendimiento en comparación con otros tiempos de ejecución de JavaScript y un ahorro de costos de 2 veces, incluso para inicios en caliente.
Entonces, ¿qué hace que esto sea tan, tan rápido? ¿Qué hay debajo del capó? Utiliza un motor de JavaScript diferente en comparación con Deno o BUN. Entonces, Deno y BUN utilizan motores llamados V8 y JavaScript Core. V8 proviene del navegador Chrome y del equipo de Chrome. El equipo de Chrome ha creado un motor de JavaScript para su navegador llamado V8, mientras que BUN utiliza un motor llamado JavaScript Core que se ha divergido de Safari. Pero QuickJS, por otro lado, es un motor muy ligero. Es muy capaz, pero también es muy ligero. El motor en sí, cuando se compila, tiene menos de un megabyte. Si lo comparamos con JavaScript Core y V8, tienen más de 50 megabytes dentro de Node y BUN. LLRT también está construido en Rust utilizando el tiempo de ejecución asincrónico de Tokyo. Muchas de sus API implementadas dentro del tiempo de ejecución cumplen con la especificación de Node.js y están implementadas en Rust. El ejecutable en sí tiene menos de tres megabytes, y eso incluye el SDK de AWS.
Creo que es hora de echar un vistazo a una demostración rápida para ver cómo funciona en acción. Aquí estoy dentro de la consola de Lambda de AWS. En este ejemplo, he importado el cliente DynamoDB y el cliente de documentos DynamoDB para poner algunos eventos que llegan a Lambda de AWS en DynamoDB. También agrego una ID aleatoria y convierto el evento en una cadena, y simplemente devuelvo un código de estado de 200 y OK. Ahora ejecutemos esto usando el tiempo de ejecución regular de Node.js 20, y esta vez vemos un inicio de llamada. Vamos a la pestaña de pruebas aquí y hacemos clic en el botón de prueba. Ahora se ha ejecutado, y si examinamos los registros de ejecución aquí, podemos ver que Node.js se ejecutó con una duración de 988 milisegundos y una duración de compilación e inicio de 366 milisegundos. Entonces, en total, esto es aproximadamente un poco más de 1,2, 1,3 segundos, en realidad, y consumimos casi 88 megabytes de memoria al hacerlo. Lo que voy a hacer ahora es volver al código. Desplácese hacia abajo hasta la configuración del tiempo de ejecución, haga clic en editar y cambie a Amazon Linux 2023, siempre solo tiempo de ejecución. Guárdelo y ahora ejecutémoslo con LLRT. Como puede ver, esto fue casi instantáneo y al examinar los registros de ejecución, podemos ver que ahora tenemos una duración de 29 milisegundos y una duración de inicio de 38, lo que significa que tenemos una duración total de 69 milisegundos. Entonces, 69 milisegundos frente a 1.300 o un poco más para Node.js. Al hacerlo, solo consumimos alrededor de 20 megabytes de memoria.
3. Beneficios de LLRT
LLRT ofrece un rendimiento rápido para inicios en caliente y está optimizado para aplicaciones con latencia crítica, transformación de datos e integración con servicios de AWS. No es adecuado para simulaciones u operaciones que involucren grandes conjuntos de datos. LLRT logra velocidad al eliminar complejidades, aprovechar Rust y optimizar el SDK de AWS para Lambda. El tiempo de ejecución es ligero y está escrito principalmente en Rust. Carece de un compilador justo a tiempo pero proporciona beneficios de rendimiento instantáneos sin depender del perfil JIT.
Y observe que si ejecuto el code nuevamente, para inicios en caliente, también es muy rápido. Aquí tenemos 45 milisegundos, 16, 13, 14, 9, etc. Por lo tanto, tampoco hay sacrificio en el rendimiento en caliente, y de hecho, puede ser hasta dos veces menor que el equivalente de Node.js, principalmente debido a la falta de un compilador justo a tiempo y un motor más simple para menos complejidad. También observe que no cambié ni una sola línea de code. Lo que hice simplemente fue cambiar la configuración del tiempo de ejecución aquí, y preparé esta demostración colocando el binario de inicio de LLRT aquí. Simplemente descargué LLRT, renombré el binario de inicio y lo coloqué junto con mi muestra de code aquí.
Bien, volvamos a la presentación. Entonces, ¿cuáles pueden ser buenos casos de uso para LLRT? Buenos casos de uso pueden ser aplicaciones con latencia crítica, funciones de alto volumen, transformación de datos, integración con diferentes servicios de AWS, e incluso aplicaciones de React renderizadas en el lado del servidor pueden ejecutarse con LLRT. También aplicaciones que consisten en mucho code de enlace. Lo que quiero decir con esto es que son aplicaciones que se integran con otras fuentes de terceros u otros servicios de AWS, que son el enlace entre un servicio y otro. Cuando no es bueno usar LLRT es cuando se realizan simulaciones o se manejan cientos o miles de iteraciones en bucles o se realizan operaciones de multidifusión, o se transfieren objetos grandes o conjuntos grandes de datos en decenas o incluso cientos de megabytes. Aquí es donde realmente brilla el compilador justo a tiempo, que es una característica que no está disponible en LLRT.
Pero lo mejor ahora es medir y ver, y estoy bastante seguro de que muchos de sus casos de uso se beneficiarían al ejecutar LLRT. Y nuevamente, ¿cómo puede ser tan rápido? No tiene JIT y el SDK de AWS está optimizado específicamente para Lambda. Esto significa que hemos eliminado algunas de las complejidades que involucra el SDK de base de datos, como el caché de creación de objetos, convertimos el SDK a código de bytes QuickJS y tenemos mucho como el caché de creación de objetos, convertimos el SDK a código de bytes QuickJS. Y aprovechamos otras técnicas que optimizan los inicios de code en Lambda. Por ejemplo, hacemos todo el trabajo posible, porque los tiempos de ejecución de Lambda tienen un impulso de CPU cuando se están inicializando. También escribimos la mayor parte de nuestro code en Rust. De hecho, tenemos una política que dice que tanto como sea posible debe escribirse en Rust. Por lo tanto, cuanto más code podamos mover de JavaScript a Rust, habrá un beneficio de rendimiento. En contraste con Node.js, casi todas sus API están escritas en JavaScript. Y dependen en gran medida del compilador justo a tiempo del motor V8 para lograr un gran rendimiento. Dado que carecemos de esta capacidad y escribimos la mayor parte del code en Rust, obtenemos beneficios de rendimiento manteniendo el tamaño bajo y obteniendo un beneficio de rendimiento instantáneo sin tener que depender del perfil JIT para optimizar el code en tareas de ejecución más largas. Básicamente, todo lo que se utiliza en LLRT está escrito en Rust. Entonces, la consola, los temporizadores, la criptografía, el hash, todo eso está escrito en Rust. Solo hay una pequeña capa de JavaScript encima de eso. Y, por supuesto, su code también se ejecutará en JavaScript. Y también, nuevamente, es muy ligero. Solo ocupa unos pocos megabytes y tratamos de mantenerlo lo más ligero posible, minimizando las dependencias, pero también minimizando la complejidad. Entonces, ¿cuál es la trampa? Esta es una matriz de compatibilidad de alto nivel.
4. LLRT Usage
LLRT tiene compensaciones en términos de las API de Node.js admitidas. No está completamente admitido, pero se está construyendo constantemente y está disponible como versión beta. Para usar LLRT, descargue la última versión desde la página de GitHub, agregue el ejecutable de inicio con su código y seleccione tiempo de ejecución personalizado en Amazon Linux 3 dentro de Lambda. LLRT se ejecuta en instancias Arm o x86-64 con una ligera ventaja al usar Arm para ahorrar costos y obtener un mejor rendimiento.
Puedes ver que hay un signo de exclamación aquí y algunas marcas de verificación. Obviamente, tiene que haber algún tipo de compensación para lograr este nivel de rendimiento. Y la compensación es que no se admiten todas las API de Node.js, pero admitimos algunas de ellas. Y tampoco están completamente admitidas. Entonces, aunque hay una marca de verificación aquí, no significa que admita, por ejemplo, el módulo FS completo o el módulo FS promises. Está parcialmente admitido. Pero estamos construyendo constantemente este tiempo de ejecución y está disponible como versión beta hoy, que puedes probar. Y más adelante en esta presentación, tendré enlaces a ello.
¿Y cómo se usa? Como viste en la demostración, simplemente descargo la última versión desde la página de GitHub, que es github.com slash AWS Labs slash LLRT. Agrego el ejecutable de inicio junto con tu código. También puedo usar una capa, si eso es lo que prefieres, o empaquetarlo como una imagen de contenedor. Luego selecciono tiempo de ejecución personalizado en Amazon Linux 3 dentro de Lambda como mi elección de tiempo de ejecución. Y LLRT se ejecuta en instancias Arm o x86-64. Hay una ligera ventaja al usar Arm porque obtienes un beneficio de ahorro de costos y también es ligeramente mejor en rendimiento. Así que esto es algo que recomiendo.
5. LLRT Performance Analysis
LLRT comienza casi seis veces más rápido que Node.js, mostrando la ligereza del motor. Los números de rendimiento muestran una mejora de rendimiento de 23 veces para los arranques en frío y una mejora de 15 veces para el peor caso. LLRT solo introdujo 109 arranques en frío en comparación con los 554 arranques en frío de Node.js. El intervalo de duración de los arranques en caliente es de 158 milisegundos para el más lento y 29 milisegundos para p99 con LLRT. LLRT ofrece un ahorro de costos de 2.9 veces y un ahorro de tiempo de 3.7 veces en comparación con Node.js. Por favor, prueba LLRT, pero recuerda que aún es experimental.
Ahora echemos un vistazo a algunos datos de referencia. Como vimos en la demostración, hicimos una muestra muy rápida donde vimos los beneficios de los arranques en frío y también los beneficios de los arranques en caliente en comparación con Node.js. Esta diapositiva muestra algunos beneficios de inicio cuando se ejecuta en mi máquina local. Como puedes ver aquí en la demostración, resaltado por la flecha, LLRT comienza casi seis veces más rápido que Node.js. Esta es una demostración bastante poco emocionante donde básicamente hacemos una impresión, pero muestra la ligereza del motor, donde no tiene que cargar muchos recursos para iniciar. Por lo tanto, puede ser incluso más rápido que Dino y Bun. Pero ten en cuenta que gran parte de esta velocidad proviene de la simplicidad. Es muy fácil introducir un nuevo tiempo de ejecución con una API limitada y decir que es más rápido. Pero este es uno de los compromisos, ¿verdad? Lo hacemos muy ligero, por lo tanto, también es naturalmente más rápido.
Ahora echemos un vistazo rápido a algunos números de rendimiento al ejecutar LLRT durante un período más largo de tiempo. Nuevamente, esto se hace con un DynamoDB PUT. Es el mismo código de muestra que vimos en la demostración. Pero ahora se ejecuta durante 32,000 invocaciones en ARM64 con 128 megabytes de memoria. Observa aquí que la latencia P99, lo que significa que el 99% de todas las invocaciones están por debajo de este número. Tenemos 34 milisegundos para los arranques en caliente y 84 milisegundos para los arranques en frío. En comparación, tenemos el arranque en caliente más rápido que es de solo 5.29 milisegundos y el arranque en frío más rápido que es de 48.85 milisegundos. Si lo comparamos con Node 18, podemos ver que tenemos una latencia P99 de 164 para los arranques en caliente y 1306 para los arranques en frío. Para los tiempos más lentos y los tiempos más rápidos, tenemos 5.85 y 1141 milisegundos para un arranque en frío. Esto significa que hay una mejora de rendimiento de 23 veces para esta demostración exacta. Para los arranques en frío y una mejora de rendimiento de 15 veces para el peor caso. Por lo tanto, este es el mejor caso versus el peor caso. También observa la cantidad de arranques en frío que puedes ver aquí. En Lambda, aunque los arranques en frío pueden no ser tan críticos para tu aplicación, si podemos mantenerlos más bajos, también significa que es menos probable que ocurran. Porque cada vez que Lambda tiene que procesar dos eventos consecutivos y no lo ha hecho antes, lo que significa que no hay instancias listas. Tiene que iniciar una nueva, lo que significa que se introducirá un arranque en frío adicional. Entonces, en mi ejemplo aquí, podemos ver que LLRT solo introdujo 109 arranques en frío en comparación con Node.js que tuvo 554 arranques en frío. Y nuevamente, esto se debe a que el proceso es mucho más corto, también es menos probable que ocurra en primer lugar. También observa aquí el intervalo de duración de los arranques en caliente, tenemos 158 milisegundos para el más lento, hasta la invocación más rápida para el arranque en caliente, en comparación con solo 29 para p99 con LLRT. Y nuevamente, esto se debe a la falta de tiempo de ajuste del compilador, lo que hace que la ejecución sea mucho más consistente. Si observamos el desglose de latencia y costos, podemos ver que tenemos una duración de compilación de 22 minutos y 19 segundos para Node.js versus LLRT, solo tenemos 7 minutos y 48 segundos, lo que se traduce en un ahorro de costos de 2.9 veces y un ahorro de tiempo de 3.7 veces. Y la razón por la que estos dos difieren es que depende de cómo se les cobre. Para los tiempos de ejecución proporcionados, se cobra de manera un poco diferente en Lambda que para los tiempos de ejecución personalizados, pero aún tenemos un ahorro de costos de 2.9x para este ejemplo en particular durante 32,000 invocaciones.
Y eso es todo por mi parte. Te animo encarecidamente a probar LLRT para que puedas seguir el enlace QR aquí. Y por favor, pruébalo. Aún es un tiempo de ejecución muy experimental, así que no lo ejecutes en producción todavía, pero estamos desarrollando más capacidades todos los días. Y esperamos que nos des tu opinión. Y nuevamente, estoy muy, muy agradecido de que hayas tomado el tiempo para escucharme hoy.
Comments