Consejos de rendimiento de Node.js en tiempo de ejecución

Rate this content
Bookmark

Node.js ejecuta grandes sistemas hoy en día. A veces, puedes mejorar la experiencia del usuario y ahorrar en gastos en la nube optimizando tus scripts de Node.js. En esta charla compartiré consejos de producción sobre cómo mejorar el rendimiento en tiempo de ejecución de Node.js.

9 min
24 Jun, 2021

Video Summary and Transcription

Esta charla se centra en la importancia de la optimización en tiempo de ejecución en el desarrollo de software. Se discute el impacto de las funciones no optimizadas y el papel de la recolección de basura. La charla también destaca el uso de herramientas de perfilado para identificar y mejorar problemas de rendimiento. Además, se enfatiza la importancia del perfilado de memoria para prevenir fugas de memoria y optimizar el rendimiento de la aplicación.

Available in English

1. Introducción a la Optimización en Tiempo de Ejecución

Short description:

Hace muchos años, me encontré con un problema crítico en un gran sistema donde un microservicio tartamudeante causaba retrasos de 2-3 segundos. Como arquitecto de software en Vonage, he dedicado años a optimizar técnicas de tiempo de ejecución. En esta parte, exploraremos cómo identificar y mejorar el rendimiento de las funciones no optimizadas, utilizando un ejemplo sencillo. También discutiremos el impacto de la recolección de basura y la importancia de la optimización en tiempo de ejecución.

Hace muchos años, estaba trabajando en un gran sistema, un sistema crítico de vida o muerte. El sistema funcionaba bien, hasta que un día recibí una llamada de un cliente. Yonatan, dice, el sistema no está respondiendo mis llamadas. Lo que estaba experimentando era un microservicio tartamudeante en el sistema. Había una función no optimizada en el flujo de trabajo que tardaba de 2 a 3 segundos en finalizar en lugar de milisegundos. Para mi cliente, estos 2-3 segundos eran críticos, especialmente al considerar un sistema a gran escala.

Me llamo Yonatan Kra, arquitecto de software en Vonage. Soy instructor de egghead, blogger y un geek a tiempo completo. También disfruto correr. He pasado años optimizando mis técnicas de tiempo de ejecución, lo cual es importante cuando necesitas huir de los matones. Hoy te mostraré cómo detectar funciones no optimizadas y cómo mejorar el rendimiento en tiempo de ejecución en tus aplicaciones.

Comenzaremos mirando un ejemplo sencillo. Aquí tenemos dos funciones que hacen lo mismo. Ambas crean un array y añaden elementos al array. BuildArray1 crea un array vacío y añade dinámicamente los índices al array. BuildArray2 preasigna el array y simplemente establece el valor correcto en el índice correcto. El resultado es el mismo. Veamos su perfil. En su perfil, puedes ver que BuildArray1 tardó alrededor de 40 milisegundos en ejecutarse, mientras que BuildArray2 tardó alrededor de 7 milisegundos en ejecutarse. Esa es una gran diferencia para funciones que hacen lo mismo. Si profundizamos, podremos ver que BuildArray1 tenía muchas barras grises en su interior, y estas son instancias de recolección de basura, mientras que BuildArray2 no tenía estas instancias de recolección de basura. Así es como utilizamos el perfilado para comparar el rendimiento de diferentes implementaciones de las mismas funciones, por ejemplo. Así podemos ver si las mejoras realmente mejoraron nuestras aplicaciones o buscar la solución correcta.

Una palabra sobre la recolección de basura. La recolección de basura es el proceso en el que los motores de JavaScript limpian la memoria de objetos no referenciados. Ya dije que soy corredor, y esta es una buena razón por la que me gusta correr los sábados, porque no hay recolectores de basura los sábados. ¿Por qué deberías preocuparte, en realidad, por la optimización en tiempo de ejecución? Esta es una caricatura del bucle de eventos en JavaScript. Lo que debes entender de esto es que el bucle de eventos está ejecutando tu hilo principal y está ejecutando tareas. Las tareas son en realidad los callbacks, tus funciones. Y si una tarea tarda más tiempo, bloquea el hilo principal y durante esta ejecución de la función, no se está ejecutando nada más.

2. Optimización de Funciones y Perfilado de Rendimiento

Short description:

Cuando optimizas tus funciones, es importante asegurarse de que se ejecuten sin problemas y evitar retrasos que puedan afectar las llamadas a la API y las promesas. Las herramientas de perfilado como Chrome inspect page y las herramientas de desarrollo dedicadas para node pueden ayudar a identificar y mejorar el rendimiento. El perfilado de memoria también puede revelar fugas de memoria y proporcionar soluciones. Al referenciar claramente los arrays y monitorear las asignaciones, puedes prevenir fugas de memoria y optimizar el rendimiento de tu aplicación.

Entonces, si esta función se está ejecutando, no se están atendiendo las llamadas a la API, no se están resolviendo las promesas y tu aplicación simplemente se queda bloqueada y todo lo demás está esperando. Esta es una buena razón para optimizar tus funciones y asegurarte de que todo funcione sin problemas.

Veamos un ejemplo de eso. Para esto, iremos al IDE. Mira esta función, algo bastante notable. Deberías estar familiarizado, es un array al que se le agregan un millón de elementos y hemos agregado un setInterval que se asegura de que se llame una vez por segundo.

Entonces, si ejecutamos nuestro node con la bandera --inspect, lo siento, inicia node en modo de depuración y podemos ir a la página de inspección de Chrome, abrir las herramientas de desarrollo dedicadas para node y ir a la página del perfilador. Esta vez, comenzaremos a grabar durante dos o tres segundos, finalizamos y aquí vamos. Tenemos nuestros intervalos, uno por segundo, y si profundizamos, en realidad vemos nuestra llamada a algo bastante notable y exactamente cuánto tiempo tardó la función en ejecutarse. De esta manera, podemos perfilar todo en nuestra aplicación de node. Por ejemplo, puedes iniciar una llamada a la API usando Postman y rastrear todo lo que sucede desde el momento en que la llamada a la API llega al servidor hasta que se agota y puedes ver cuánto tiempo tardó cada función en ejecutarse y si ves una función que tarda mucho tiempo, es posible que desees optimizar esta función.

Otro problema en el rendimiento en tiempo de ejecución es la memoria y pronto veremos cómo perfilar la memoria y tal vez incluso solucionar fugas de memoria. En este caso, algo bastante notable, se agrega a un array que se crea externamente, por lo que en cada intervalo, simplemente aumentamos este array y no recolectamos basura del array interno que teníamos antes. Veamos cómo se ve esto cuando perfilar la memoria.

Entonces, comienzo nuevamente en modo de depuración. Esta vez iré a la pestaña de memoria y me aseguro de que la instrumentación de asignación en la línea de tiempo esté funcionando. Comienzo a grabar y veo que aparecen estas barras azules. Una barra azul significa una memoria que se asignó y no se recolectó basura. Y si me enfoco en una de ellas, en realidad veo estos 100 especiales como se esperaba. En cada segundo se asignaron 100 especiales y no se borraron. Si me enfoco en uno de los especiales, puedo ver su índice en el array, el nombre del array de referencia e incluso la línea de código que asignó este objeto. Puedo ver fácilmente si quiero que este objeto se recolecte basura o no. Si quiero que se recolecte basura, entonces tengo una fuga.

Arreglemos esta fuga bastante fácilmente simplemente borrando el array de referencia en cada intervalo. Detendré el servidor, lo reiniciaré y grabemos nuevamente. Ahora, la barra azul se vuelve gris. El gris significa que tuvimos una asignación aquí, pero se recolectó basura. Nuevamente, puedes llamar a tu API, ver si tienes una barra azul que se vuelve gris después de que la API termine de ejecutarse y si no, es posible que tengas una fuga de memoria en el controlador de tu API, por ejemplo.

Por lo general, cuando hablo con desarrolladores sobre el rendimiento o ayudo a los desarrolladores a resolver problemas de rendimiento, veo mucha confusión en cuanto a cómo manejar los problemas de rendimiento. Espero que esta charla te haya ayudado a comprender las herramientas de perfilado que tienes, las poderosas herramientas de perfilado que tienes y cómo puedes ayudar a que tus funciones se ejecuten más rápido y prevenir fugas de memoria en tus aplicaciones. Realmente espero haber despertado tu interés para aprender más sobre este tema. Estoy muy apasionado al respecto y espero que lo disfrutes tanto como yo. ¡Gracias!

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Too much JavaScript is getting you down? New frameworks promising no JavaScript look interesting, but you have an existing React application to maintain. What if Qwik React is your answer for faster applications startup and better user experience? Qwik React allows you to easily turn your React application into a collection of islands, which can be SSRed and delayed hydrated, and in some instances, hydration skipped altogether. And all of this in an incremental way without a rewrite.
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.
Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Top Content
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
Node Congress 2023Node Congress 2023
109 min
Node.js Masterclass
Workshop
Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate
React Advanced Conference 2023React Advanced Conference 2023
148 min
React Performance Debugging
Workshop
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
WorkshopFree
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow (https://platformatic.dev/). 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.