Saltar al contenido principal

Retirando Octane

· 7 min de lectura
el equipo de V8

La historia de los benchmarks de JavaScript es una historia de evolución constante. A medida que la web se expandió de simples documentos a aplicaciones dinámicas del lado del cliente, se crearon nuevos benchmarks de JavaScript para medir cargas de trabajo que se volvieron importantes para nuevos casos de uso. Este cambio constante ha dado a los benchmarks individuales una vida útil limitada. A medida que los navegadores web y las implementaciones de máquinas virtuales (VM) comienzan a sobreoptimizar casos de prueba específicos, los propios benchmarks dejan de ser proxies efectivos para sus casos de uso originales. Uno de los primeros benchmarks de JavaScript, SunSpider, proporcionó incentivos tempranos para implementar compiladores de optimización rápidos. Sin embargo, a medida que los ingenieros de VM descubrieron las limitaciones de los microbenchmarks y encontraron nuevas formas de optimizar en torno a las limitaciones de SunSpider, la comunidad de navegadores retiró SunSpider como un benchmark recomendado.

El origen de Octane

Diseñado para mitigar algunas de las debilidades de los primeros microbenchmarks, el conjunto de pruebas Octane se lanzó por primera vez en 2012. Evolucionó a partir de un conjunto anterior de simples casos de prueba de V8 y se convirtió en un benchmark común para el rendimiento general de la web. Octane consta de 17 pruebas diferentes, diseñadas para cubrir una variedad de cargas de trabajo, que van desde la prueba de simulación de kernel de Martin Richards hasta una versión del compilador TypeScript de Microsoft compilándose a sí mismo. El contenido de Octane representaba la sabiduría prevalente sobre cómo medir el rendimiento de JavaScript en el momento de su creación.

Rendimientos decrecientes y sobreoptimización

En los primeros años después de su lanzamiento, Octane proporcionó un valor único al ecosistema de máquinas virtuales de JavaScript. Permitió que los motores, incluido V8, optimizaran su rendimiento para una clase de aplicaciones que requerían un rendimiento máximo. Estas cargas de trabajo intensivas en CPU inicialmente estaban poco atendidas por las implementaciones de VM. Octane ayudó a los desarrolladores de motores a proporcionar optimizaciones que permitieron que las aplicaciones intensivas en cálculos alcanzaran velocidades que hicieron que JavaScript fuera una alternativa viable a C++ o Java. Además, Octane impulsó mejoras en la recolección de basura que ayudaron a los navegadores web a evitar pausas largas o impredecibles.

Para 2015, sin embargo, la mayoría de las implementaciones de JavaScript habían implementado las optimizaciones de compilación necesarias para obtener altas puntuaciones en Octane. Esforzarse por obtener puntuaciones aún más altas en Octane se tradujo en mejoras cada vez más marginales en el rendimiento de las páginas web reales. Las investigaciones sobre el perfil de ejecución de Octane versus la carga de sitios web comunes (como Facebook, Twitter o Wikipedia) revelaron que el benchmark no ejercita el analizador de V8 o la pila de carga del navegador de la misma manera que lo hace el código del mundo real. Además, el estilo del JavaScript de Octane no coincide con los patrones e idiomas utilizados por la mayoría de los frameworks y bibliotecas modernas (sin mencionar el código transpilado o las funciones más recientes del lenguaje ES2015+). Esto significa que utilizar Octane para medir el rendimiento de V8 no capturaba casos de uso importantes para la web moderna, como cargar frameworks rápidamente, soportar aplicaciones grandes con nuevos patrones de gestión de estado o garantizar que las funciones ES2015+ sean tan rápidas como sus equivalentes en ES5.

Además, comenzamos a notar que las optimizaciones en JavaScript que lograban puntajes Octane más altos a menudo tenían un efecto perjudicial en escenarios del mundo real. Octane fomenta la inlining agresiva para minimizar la sobrecarga de llamadas a funciones, pero estrategias de inlining adaptadas a Octane han llevado a regresiones debido a costos de compilación elevados y mayor uso de memoria en casos de uso reales. Incluso cuando una optimización puede ser realmente útil en el mundo real, como es el caso de preasignación dinámica, perseguir puntajes más altos en Octane puede resultar en el desarrollo de heurísticas excesivamente específicas que tienen poco efecto o incluso degradan el rendimiento en casos más genéricos. Descubrimos que las heurísticas de preasignación derivadas de Octane llevaron a degradaciones de rendimiento en frameworks modernos como Ember. El operador instanceof fue otro ejemplo de una optimización adaptada a un conjunto específico de casos de Octane que llevó a regresiones significativas en aplicaciones de Node.js.

Otro problema es que, con el tiempo, pequeños errores en Octane se convierten en un objetivo para optimizaciones en sí mismas. Por ejemplo, en el benchmark Box2DWeb, aprovechar un error donde dos objetos se comparaban usando los operadores < y >= proporcionó un aumento de ~15% en el rendimiento de Octane. Desafortunadamente, esta optimización no tuvo efecto en el mundo real y complicó tipos de optimizaciones de comparación más generales. Octane a veces incluso penaliza negativamente las optimizaciones del mundo real: los ingenieros que trabajan en otras máquinas virtuales han notado que Octane parece penalizar la interpretación diferida, una técnica que ayuda a cargar la mayoría de los sitios web reales más rápido dado la cantidad de código residual que se encuentra frecuentemente.

Más allá de Octane y otros benchmarks sintéticos

Estos ejemplos son solo algunos de los muchos casos en que las optimizaciones aumentaron los puntajes de Octane en detrimento de la ejecución de sitios web reales. Desafortunadamente, problemas similares existen en otros benchmarks estáticos o sintéticos, incluidos Kraken y JetStream. En pocas palabras, dichos benchmarks son métodos insuficientes para medir la velocidad en el mundo real y generan incentivos para que los ingenieros de VM sobreoptimicen casos de uso específicos y suboptimicen casos genéricos, ralentizando el código JavaScript en el entorno real.

Dado el estancamiento en los puntajes entre la mayoría de las máquinas virtuales JavaScript y el creciente conflicto entre optimizar benchmarks específicos de Octane en lugar de implementar mejoras de velocidad para un rango más amplio de código del mundo real, creemos que es momento de retirar Octane como benchmark recomendado.

Octane permitió al ecosistema de JS lograr grandes avances en JavaScript computacionalmente costoso. Sin embargo, la próxima frontera es mejorar el rendimiento de páginas web reales, bibliotecas modernas, frameworks, características de lenguaje ES2015+ , nuevos patrones de gestión de estado, asignación de objetos inmutables y empaquetado de módulos . Dado que V8 se ejecuta en muchos entornos, incluido el lado del servidor en Node.js, también estamos invirtiendo tiempo en entender aplicaciones reales de Node y en medir el rendimiento de JavaScript del servidor a través de cargas de trabajo como AcmeAir.

Vuelve aquí para más publicaciones sobre mejoras en nuestra metodología de medición y nuevas cargas de trabajo que representan mejor el rendimiento del mundo real. ¡Estamos emocionados de continuar buscando el rendimiento que más importa a usuarios y desarrolladores!