Inline Caches (IC)
Inline Caches — механизм V8 для кэширования результатов lookup свойств прямо в точке вызова; переход из monomorphic → polymorphic → megamorphic резко снижает производительность и диагностируется через —trace-ic.
// IC состояния и их влияние на производительностьfunction getX(obj) { return obj.x; } // IC site внутри функции
// Monomorphic: один тип входящего объекта → кэш одной Mapconst a = { x: 1 };for (let i = 0; i < 1e5; i++) getX(a); // IC: monomorphic// TurboFan: прямой доступ по fixed offset → почти бесплатно
// Polymorphic: 2-4 разных Map → IC как небольшой vtableconst b = { x: 2, y: 3 }; // другая Map!getX(b); // IC: polymorphic (2 entries)
// Megamorphic: 5+ разных Map → IC отказывается кэшироватьconst shapes = [ { x: 1 }, { x: 2, a: 1 }, { x: 3, b: 1 }, { x: 4, c: 1 }, { x: 5, d: 1 }, // 5+ форм];shapes.forEach(o => getX(o)); // megamorphic → generic lookup каждый раз// Загрузочные IC (LOAD) vs вызывные IC (CALL)class Animal { speak() { return 'sound'; } }class Dog extends Animal { speak() { return 'woof'; } }class Cat extends Animal { speak() { return 'meow'; } }
function makeSpeak(animal) { return animal.speak(); // CALL IC}
const dog = new Dog();for (let i = 0; i < 1e5; i++) makeSpeak(dog); // monomorphic → inlined
makeSpeak(new Cat()); // polymorphic — V8 создаёт двойную проверку
// Паттерн: держать CALL IC monomorphic в hot path → inlining работает// Если нужен полиморфизм — интерфейс с одинаковой скрытой структурой// Диагностика через Node.js// node --trace-ic --allow-natives-syntax script.js// → LOAD/STORE/CALL IC переходы: 0→1 (mono), 1→2 (poly), ...→X (mega)
// Benchmark: monomorphic vs megamorphic ICfunction bench() { const mono = { x: 1 }; function readMono() { return mono.x; }
// прогрев for (let i = 0; i < 1e5; i++) readMono();
console.time('mono'); for (let i = 0; i < 1e8; i++) mono.x; // ~50ms console.timeEnd('mono');
// megamorphic — передаём 10 разных форм const poly = Array.from({ length: 10 }, (_, i) => Object.assign({ x: i }, ...Array.from({ length: i }, (_, j) => ({ [j]: j }))) ); console.time('mega'); for (let i = 0; i < 1e8; i++) poly[i % 10].x; // ~400ms console.timeEnd('mega');}Итог: IC — ключевой механизм оптимизации доступа к свойствам; monomorphic IC = почти бесплатный доступ с возможностью inlining, megamorphic = полный generic lookup при каждом обращении.