OSR — On-Stack Replacement
Самая сложная оптимизация V8: замена кода прямо во время выполнения функции, на горячем цикле внутри ещё неоптимизированной функции. Может ускорить или замедлить идентичный код в 10 раз.
Зачем нужен OSR
V8 оптимизирует функцию целиком. Но что если функция вызвана 1-2 раза, а внутри неё цикл на миллион итераций? Никто не вызовет функцию 100500 раз ради оптимизации, а цикл прогоняется бесконечно.
OSR решает это: оптимизирует кусок кода внутри цикла, а не функцию.
Механика
- Функция выполняется в Ignition (байт-код).
- На входе цикла V8 ставит счётчик итераций.
- Достигли порога — генерируется оптимизированная машинная версия именно для тела цикла.
- Стек подменяется на лету: текущий фрейм Ignition заменяется на TurboFan-фрейм с теми же локальными переменными.
- По завершении функции OSR-оптимизация забывается (в новом V8 есть доп. кэши, но не всегда срабатывают).
Подводные камни
- OSR работает не с функцией, а с её кусочком — часть остаётся байт-кодом, часть оптимизируется.
- Логи V8 показывают три буквы
OSR— туда стоит смотреть. - Известен баг V8: одинаковый код с OSR может работать в 10 раз медленнее в зависимости от мелочей (
forvswhile, форма выхода). - Не пиши гигантских циклов в одноразовых функциях — раскладывай на отдельные функции с горячей частью.
Источники
- 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