- En un benchmark del desarrollador independiente Theo Browne, Cloudflare Workers mostró un rendimiento de hasta 3.5 veces más lento que Vercel Node.js
- La causa de los resultados del benchmark se debió a varios problemas de configuración de infraestructura y bibliotecas, además de fallas metodológicas del benchmark
- Se realizaron múltiples mejoras de plataforma y framework, como mejoras en el algoritmo de scheduling, ajuste del recolector de basura de V8 y optimización de OpenNext
- Gracias a parches clave, actualmente la diferencia de rendimiento entre Cloudflare y Vercel se ha reducido considerablemente en la mayoría de los benchmarks
- En adelante, Cloudflare seguirá contribuyendo a mejoras en infraestructura y frameworks públicos, además de continuar con la optimización y la validación de benchmarks
Resumen general y controversia del benchmark
- En octubre de 2023, el desarrollador Theo Browne publicó un benchmark que comparaba la velocidad de ejecución de JavaScript del lado del servidor entre Cloudflare Workers y Vercel (basado en AWS Lambda)
- Cloudflare Workers también se basa en el motor JavaScript V8, igual que Vercel, pero se observó una degradación de rendimiento de hasta 3.5 veces
- Se generó una brecha de rendimiento poco razonable por diversas causas, como ajuste fino de infraestructura, diferencias entre bibliotecas de JavaScript y problemas en la forma de prueba
- En el proceso de corregir estos problemas, mejoró el rendimiento general de Cloudflare Workers
- Entre los cambios principales también se incluyeron mejoras que podrían impactar otras plataformas, como una mejora en la velocidad de operaciones trigonométricas
Metodología del benchmark
- El cliente de prueba original de Theo accedía desde San Francisco mediante Webpass, y Vercel se ejecutaba en la región sfo1
- En Cloudflare se minimizó el impacto de la latencia de red al comunicarse directamente con la instancia iad1 de Vercel desde un centro de datos de AWS en us-east-1
- Todos los benchmarks se realizaron en un entorno de un solo hilo (1 vCPU), lo que también facilitó igualar la comparación de precios
- Los bugs descubiertos durante las pruebas se enviaron upstream mediante Pull Request y fueron corregidos
Mejoras de rendimiento en la plataforma de Cloudflare
Mejoras en scheduling y manejo de aislamiento en Workers Runtime
- Antes se usaba un algoritmo que enrutaba el tráfico hacia aislamientos "calientes" (instancias que pueden procesar rápido) para optimizar la latencia y el throughput de aplicaciones grandes, pero era ineficiente para cargas de trabajo intensivas en CPU
- Cuando se acumulaban solicitudes con alto consumo de CPU, las colas se alargaban y aumentaba la latencia, algo que se hizo visible en el benchmark
- Como Cloudflare Workers factura según el tiempo de uso de CPU, el tiempo de espera (espera de preparación del aislamiento) no se cobra
- Mediante una revisión del algoritmo, se mejoró la detección rápida de cargas con alto uso de CPU y la creación acelerada de nuevos aislamientos
- Esto permite responder eficientemente tanto a cargas I/O-bound como CPU-bound, y el cambio se desplegó globalmente con efecto inmediato
Mejora en la configuración del recolector de basura de V8
- Durante las pruebas se confirmó que los problemas de garbage collection y manejo de memoria en JavaScript impactaban mucho el rendimiento
- La configuración del tamaño del área de memoria "young generation" del motor V8 estaba fijada de forma demasiado restrictiva (ajustada a la antigua recomendación de 128 MB)
- En V8 moderno, esa forma de configuración más bien provoca GC frecuentes e innecesarios
- Se desactivó el ajuste manual y se permitió la asignación dinámica de memoria basada en heurísticas del propio V8
- Se confirmó una mejora de alrededor del 25% en el rendimiento del benchmark, aplicada a todos los Workers
Optimización de rendimiento de Next.js basado en OpenNext
Eliminación de asignaciones y copias de memoria innecesarias
- El análisis mostró que entre 10% y 25% del tiempo de procesamiento de solicitudes se gastaba en liberar memoria (GC)
- OpenNext, Next.js y React tenían múltiples patrones de código que copiaban en exceso buffers de datos internos
- Se hacían copias innecesarias de todos los datos de salida de streams, y con
Buffer.concat se copiaban grandes volúmenes de datos solo para medir longitud simple
- Estos problemas relacionados se están mejorando mediante Pull Request en el repositorio de OpenNext
- Se planea seguir refinando esto para que la mejora de rendimiento beneficie de forma común a toda la plataforma
Optimización de adaptadores de streams ineficientes
- Workers está diseñado principalmente sobre Web Streams API, mientras que Next.js se diseñó en torno a la API de streams de Node.js, por lo que se necesita un adaptador de conversión
- El uso innecesario de adaptadores anidados generaba múltiples sobrecostos de copia de memoria y buffering
- El código se simplificó a
ReadableStream.from(chunks) para eliminar copias intermedias
- La estructura predeterminada de stream de valor único (
highWaterMark=1) se mejoró a un stream de bytes (highWaterMark=4096, etc.) para optimizar el manejo de grandes volúmenes de datos
- Más adelante también se enviarán upstream a plataformas superiores parches para mejorar el procesamiento de streams en Next.js y React
Problema de rendimiento de JSON.parse() y parche en V8
- En Next.js y React en general se producían llamadas excesivas al usar
JSON.parse() con la opción reviver (más de 100,000 veces)
- En el estándar ECMAScript más reciente, el reviver puede recibir un tercer argumento (source context), lo que empeoró aún más el rendimiento (en Firefox, Chrome y otros por igual)
- El equipo de Cloudflare Workers aportó un parche al motor V8 (mejora de rendimiento del 33%), lo que beneficiará a todo el ecosistema, incluyendo Node.js, el navegador Chrome y Deno
Problema de rendimiento trigonométrico en Node.js
- Independientemente del benchmark de Theo, se reportó que Cloudflare Workers era 3 veces más rápido en un benchmark de llamadas repetidas a funciones trigonométricas matemáticas (
sin, cos, etc.)
- La causa fue que Node.js todavía no se había adaptado a la ruta trigonométrica más reciente y rápida que ofrece V8 (compile-time flag)
- Cloudflare Workers tenía esa flag activada por defecto por casualidad, y se envió un Pull Request con el parche para Node.js
- Como este problema también es común en el ecosistema open source, se espera una estabilización general de velocidad cuando también se refleje en AWS Lambda y Vercel
Limitaciones y lecciones del diseño/medición del benchmark
- La mayoría de los benchmarks medían el tiempo de solicitud (latency) desde el cliente, sin medir directamente el tiempo real de uso de CPU del lado del servidor
- Diversas variables no comparables, como la ruta de red, ubicación del centro de datos, generación de hardware y multitenancy, pueden afectar los resultados
- Si solo se mide el tiempo hasta el primer byte de respuesta (TTFB), es difícil reflejar el tiempo total de renderizado/transmisión. Si se cambia a TTFL, puede volverse más sensible a las diferencias de velocidad de red
- También existe ruido temporal o correlacionado debido a la diversidad de hardware/software del servidor y a la suerte en la asignación de instancias
- Al precisar el entorno y el flujo de trabajo del benchmark y al alinear variables, se identificaron mejoras prácticas que beneficiaron tanto a la propia plataforma como a plataformas de terceros
Problemas descubiertos en el benchmark y en la configuración del entorno durante el experimento
- Había riesgo de malinterpretar los resultados por diferencias como la no aplicación de la configuración force-dynamic de Next.js, la lógica de caché y la forma de streaming de respuestas
- En el benchmark de React SSR, la variable de entorno NODE_ENV no estaba definida, por lo que corría en dev mode y devolvía resultados más lentos de lo real
- Estos errores se corrigieron estableciendo explícitamente las variables de entorno
Planes a futuro y conclusión
- Las diversas mejoras de rendimiento en Cloudflare Workers Runtime ya fueron aplicadas de forma general, por lo que los usuarios se benefician sin hacer nada adicional
- Se proporcionaron a Theo Pull Request con el código de prueba y optimizaciones de OpenNext ya reflejadas
- Se prevén mejoras adicionales para cerrar la brecha entre OpenNext y Next.js basado en Vercel
- Se mantendrá la política de seguir actualizando el algoritmo de scheduling y los motores open source (V8, Node.js), además de contribuir a la comunidad
- Con mejores benchmarks y profiling, se planea detectar antes los problemas potenciales y mantener la cultura de optimización y de compartir mejoras
Material de referencia y enlaces adicionales
1 comentarios
Opiniones en Hacker News
Es bueno que CF realmente esté intentando mejorar el producto. Pero los cambios suceden tan rápido que es difícil seguirles el ritmo, y muchas veces los lanzamientos se adelantan al nivel de madurez. Por ejemplo, R2 Data Catalog todavía carece de soporte suficiente para Iceberg v3, Wrangler cambió bastante en apenas unos meses, y parece que Pages va a desaparecer pronto, así que migrar a Workers Assets es bastante engorroso. Configuraciones que funcionaban bien en Wrangler 3 no se aplicaron correctamente en Wrangler 4, y da la impresión de que en Wrangler 5 volverá a aparecer un nuevo modelo de interacción
Sobre eso de que "parece que Pages va a desaparecer pronto", en realidad CF mencionó en una publicación de la comunidad que no eliminarán Pages hasta que Workers esté al mismo nivel que Pages Publicación relacionada Es difícil encontrar algo oficial que diga que Pages será descontinuado, y tanto pages.cloudflare.com como developer.cloudflare.com/pages siguen activos. Una publicación en Reddit insinúa una migración desde Pages, pero incluso en ese enlace no hay ninguna mención oficial de interrupción Coincido con el resto de la opinión, y esa parte en particular fue la que más me sorprendió Enlace de referencia en Reddit
No puedo estar de acuerdo con la afirmación de que la configuración de Wrangler 3 ya no funciona igual en Wrangler 4. En Wrangler 4 no hubo ningún cambio en el formato de configuración, y el aumento de versión mayor no afectó al 99.99% de los usuarios. Los cambios correspondientes pueden verse aquí. Como el simple aumento de versión mayor ya genera bastante molestia, yo mismo manifesté mi oposición internamente, pero el equipo actuó con cautela por casos excepcionales extremadamente raros. En adelante desarrollaremos formas de manejar este tipo de problemas sin subir la versión mayor, por ejemplo con soporte paralelo para versiones de esbuild. En lo referente al runtime, nos preocupamos muchísimo por la compatibilidad hacia atrás Blog sobre compatibilidad hacia atrás Pages no va a desaparecer, y Workers Assets es una versión más flexible de la implementación de Pages. Si no necesitas funciones adicionales, no hace falta migrar, y más adelante también se hará una migración automática
Esto recuerda una vez más que, al crear proyectos importantes o sistemas que deben mantenerse durante años, conviene usar "boring tech"
Me gustaría saber de dónde salió la idea de que "parece que Pages va a desaparecer pronto". Yo uso Pages sin problemas en varios proyectos
Lo interesante es que toda esta controversia empezó con la afirmación de que Cloudflare era más rápido que Vercel. Después, alguien que realmente sabía del tema hizo un benchmark y resultó que en realidad era al revés, y como resultado Cloudflare se puso a trabajar de verdad para mejorar el rendimiento
Me gustó mucho que, en vez de atacar a la competencia, el artículo se enfocara en identificar y resaltar puntos de mejora. También impresiona que hubo avances en la implementación de OpenNext y que eso pueda reutilizarse en otros proveedores
Estoy migrando un hosting de NextJS en Vercel hacia Astro/React en Cloudflare. Lo sorprendente es que, incluso renderizando la web en cada solicitud desde el “edge”, los tiempos de respuesta rondan entre 100 y 200 ms, una velocidad que casi no desmerece frente a una página estática. En las últimas semanas también se sienten claramente las mejoras de Cloudflare Worker: los cold starts casi desaparecieron y la velocidad de respuesta es mucho más estable Enlace de la webapp que estoy porteando
Me parece curioso que un video subido por un youtuber no tan grande se haya difundido de forma tan efectiva y terminara llevando a que Cloudflare hiciera mejoras realmente significativas y resolviera problemas de la plataforma
Es una PR demasiado bien armada. Felicitaciones a quienes prepararon esta publicación
Hablando como cliente antiguo de cf, cf no solo escribe muy bien en su blog y en sus proyectos open source, sino que además tiene el mejor soporte entre las empresas de infraestructura. Los miembros del equipo, incluido kenton, muchas veces ayudan directamente a los usuarios en Discord o toman en cuenta el feedback, y también es posible hablar de inmediato con los ingenieros responsables sobre bugs o problemas. De hecho, alguna vez incorporaron rápidamente un PR o una solicitud de feature que propuse, sin demasiados trámites. Incluso con una tarifa mucho más barata que la de otras grandes empresas, recibo un soporte bastante mejor
¡Gracias! Esta PR y esta publicación fueron planificadas y producidas de forma 100% autónoma por ingenieros del equipo de Workers (yo también participé)
Me gusta mucho la forma en que está escrita esta publicación, cómo descompone la información y cómo abre la discusión públicamente. Me da más confianza en el equipo de Cloudflare workers
En mi opinión, SvelteKit es increíblemente rápido, y Next.js es relativamente muy lento
Parece una conclusión bastante razonable
Ojalá frameworks más prácticos como SvelteKit, Astro y TanStack terminen reemplazando pronto la complejidad de NextJS
Este es un buen ejemplo de por qué hacen falta competencia y benchmarks independientes. Incluso servicios con rendimiento insuficiente terminan esforzándose por mejorar
Pero incluso ese esfuerzo solo funciona si realmente te importa el producto
Ya existen benchmarks independientes
Me impresionó que Cloudflare aceptara el resultado con humildad y mejorara de forma constructiva
Es un gran texto porque se enfoca en el contenido y no en atacar. Pero me sorprendió que Cloudflare no hubiera monitoreado y ajustado mejor de antemano cosas como el tamaño de las generations. En tuning de rendimiento de JVM, configurar el tamaño de las generations siempre me pareció algo básico