OSR — On-Stack Replacement

Самая сложная оптимизация V8: замена кода прямо во время выполнения функции, на горячем цикле внутри ещё неоптимизированной функции. Может ускорить или замедлить идентичный код в 10 раз.

Зачем нужен OSR

V8 оптимизирует функцию целиком. Но что если функция вызвана 1-2 раза, а внутри неё цикл на миллион итераций? Никто не вызовет функцию 100500 раз ради оптимизации, а цикл прогоняется бесконечно.

OSR решает это: оптимизирует кусок кода внутри цикла, а не функцию.

Механика

  1. Функция выполняется в Ignition (байт-код).
  2. На входе цикла V8 ставит счётчик итераций.
  3. Достигли порога — генерируется оптимизированная машинная версия именно для тела цикла.
  4. Стек подменяется на лету: текущий фрейм Ignition заменяется на TurboFan-фрейм с теми же локальными переменными.
  5. По завершении функции OSR-оптимизация забывается (в новом V8 есть доп. кэши, но не всегда срабатывают).

Подводные камни

  • OSR работает не с функцией, а с её кусочком — часть остаётся байт-кодом, часть оптимизируется.
  • Логи V8 показывают три буквы OSR — туда стоит смотреть.
  • Известен баг V8: одинаковый код с OSR может работать в 10 раз медленнее в зависимости от мелочей (for vs while, форма выхода).
  • Не пиши гигантских циклов в одноразовых функциях — раскладывай на отдельные функции с горячей частью.

Источники

  • OSR (On-Stack Replacement) оптимизация в V8 · AsForJS · 2025-10-13
    • Цитата: «Оптимизация кода в V8 происходит на уровне кода всей функции. V8 не оптимизирует какие-то кусочки кода.»
    • Цитата: «А что будет, если у нас есть функция, вызывается один-два раза, но внутри этой функции существует какой-то сумасшедший цикл на громаднейшее количество итераций?»
    • Бенчмарк: одинаковый код через OSR — до 10x разница в производительности
  • Расследование бага в OSR оптимизации V8 · AsForJS · 2025-10-17
  • Update to the V8 OSR Optimization Bug Investigation · AsForJS · 2025-10-17

См. также