Перейти к основному содержимому

Уход Octane

· 5 мин. чтения
команда V8

История бенчмарков JavaScript — это история постоянной эволюции. По мере того как веб развивался от простых документов до динамических клиентских приложений, создавались новые бенчмарки JavaScript, чтобы измерить рабочие нагрузки, которые становились важными для новых сценариев использования. Эти постоянные изменения определяют ограниченный срок службы отдельных бенчмарков. Когда веб-браузеры и виртуальные машины (VM) начинают чрезмерно оптимизировать конкретные тестовые сценарии, сами бенчмарки перестают быть эффективным показателем для их исходных сценариев использования. Один из первых бенчмарков JavaScript, SunSpider, дал стимул к созданию и использованию быстродействующих компиляторов. Однако, когда инженеры VM обнаружили ограничения микро-бенчмарков и нашли новые способы их оптимизации, учитывая ограничения SunSpider, сообщество браузеров перестало использовать SunSpider в качестве рекомендованного бенчмарка.

Происхождение Octane

Разработанный для смягчения некоторых слабых мест ранних микро-бенчмарков, набор бенчмарков Octane был впервые выпущен в 2012 году. Он эволюционировал из ранее разработанных простых тестовых сценариев для V8 и стал общим инструментом для измерения производительности веба. Octane включает в себя 17 различных тестов, предназначенных для охвата широкого спектра рабочих нагрузок, начиная от теста имитации ядра Мартина Ричардса до версии компилятора Microsoft TypeScript, который компилирует сам себя. Содержимое Octane отражало преобладающее представление о способах измерения производительности JavaScript на момент его создания.

Уменьшающаяся отдача и чрезмерная оптимизация

В первые несколько лет после выхода Octane представил уникальную ценность для экосистемы виртуальных машин JavaScript. Он позволил движкам, включая V8, оптимизировать производительность для класса приложений, которые требовали пикового уровня производительности. Эти ресурсоемкие рабочие нагрузки изначально поддерживались VM-реализациями недостаточно. Octane помог разработчикам движков внедрять оптимизации, которые позволили вычислительно сложным приложениям достичь скорости, делающей JavaScript жизнеспособной альтернативой C++ или Java. Кроме того, Octane способствовал улучшению управления сборкой мусора, предотвращая длительные или непредсказуемые паузы в веб-браузерах.

Однако к 2015 году большинство реализаций JavaScript внедрили оптимизации компилятора, необходимые для достижения высоких результатов в Octane. Стремление к еще более высоким показателям в Octane вело к все более незначительным улучшениям в производительности реальных веб-страниц. Исследования профиля выполнения Octane и загрузки обычных веб-сайтов (таких как Facebook, Twitter или Wikipedia) показали, что бенчмарк не использует функции парсера V8 или стека загрузки браузера так, как это делает реальный код. Более того, стиль JavaScript в Octane не соответствует идиомам и шаблонам, применяемым современными фреймворками и библиотеками (не говоря уже о транспилированном коде или функциях ES2015+). Это означает, что использование Octane для измерения производительности V8 не охватывало важные сценарии для современного веба, такие как быстрая загрузка фреймворков, поддержка крупных приложений с новыми методами управления состояниями или обеспечение того, чтобы функции ES2015+ были такими же быстрыми, как их эквиваленты из ES5.

Кроме того, мы начали замечать, что оптимизации в JavaScript, которые повышают результаты Octane, часто отрицательно влияют на реальные сценарии использования. Octane поощряет агрессивное встраивание для минимизации затрат на вызовы функций, но стратегии встраивания, адаптированные для Octane, привели к регрессиям из-за увеличенных затрат на компиляцию и более высокого использования памяти в реальных случаях. Даже если какая-либо оптимизация действительно полезна в реальных сценариях, как, например, динамическая преждевременная фиксация, стремление к более высоким результатам Octane может привести к разработке чрезмерно специфических эвристик, которые малоэффективны или даже ухудшают производительность в более общих случаях. Мы обнаружили, что эвристики преждевременной фиксации, выведенные из Octane, привели к ухудшению производительности в современных фреймворках, таких как Ember. Оператор instanceof был еще одним примером оптимизации, адаптированной к узкому набору Octane-специфических случаев, что привело к значительным регрессиям в приложениях Node.js.

Еще одной проблемой является то, что со временем небольшие ошибки в Octane сами становятся целями для оптимизаций. Например, в тесте Box2DWeb использование ошибки, при которой два объекта сравнивались с помощью операторов < и >=, дало прирост производительности около 15% в Octane. К сожалению, эта оптимизация не имела эффекта в реальном мире и усложняла более общие типы оптимизаций сравнения. Иногда Octane даже отрицательно влияет на реальные оптимизации: инженеры, работающие над другими виртуальными машинами, заметили, что Octane, похоже, штрафует за ленивую разборку, технику, которая помогает большинству реальных сайтов загружаться быстрее, учитывая количество лишнего кода, часто встречающегося в природе.

За пределами Octane и других синтетических тестов

Эти примеры представляют собой лишь часть множества оптимизаций, которые увеличивали результаты Octane в ущерб производительности реальных сайтов. К сожалению, подобные проблемы существуют и в других статических или синтетических тестах, таких как Kraken и JetStream. Проще говоря, такие тесты являются недостаточным методом измерения реальной скорости и создают стимулы для инженеров VM переоптимизировать узкие случаи и недооценивать общие, что замедляет JavaScript-код в реальной среде.

Учитывая плато в результатах большинства JS VM и возрастающий конфликт между оптимизацией для конкретных тестов Octane и внедрением ускорений для более широкого спектра реального кода, мы считаем, что пришло время отказаться от Octane как рекомендованного теста.

Octane позволил экосистеме JS добиться значительного прогресса в вычислительно сложном JavaScript. Однако следующей задачей является улучшение производительности реальных веб-страниц, современных библиотек, фреймворков, возможностей языка ES2015+ language features, новых паттернов управления состоянием, распределения неизменяемых объектов и модульной сборки. Так как V8 используется во многих средах, включая серверные на Node.js, мы также инвестируем время в понимание реальных приложений Node и измерение серверной производительности JavaScript через рабочие нагрузки, такие как AcmeAir.

Возвращайтесь сюда для более подробных публикаций о улучшениях методологии измерения и новых рабочих нагрузках, которые лучше отражают реальную производительность. Мы с нетерпением продолжаем стремиться к производительности, которая наиболее важна для пользователей и разработчиков!