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

Пользовательские снимки начальной загрузки

· 3 мин. чтения
Yang Guo ([@hashseed](https://twitter.com/hashseed)), инженер-программист и поставщик предварительного нагрева двигателя

Спецификация JavaScript включает в себя много встроенного функционала, от математических функций до полноценного движка регулярных выражений. Каждый вновь создаваемый контекст V8 имеет эти функции доступными с самого начала. Чтобы это работало, глобальный объект (например, объект window в браузере) и весь встроенный функционал должны быть настроены и инициализированы в куче V8 в момент создания контекста. На это требуется значительное время, если делать все с нуля.

К счастью, V8 использует короткий путь для ускорения процесса: подобно тому, как размораживают замороженную пиццу для быстрого ужина, мы десериализуем заранее подготовленный снимок непосредственно в кучу, чтобы получить инициализированный контекст. На обычном настольном компьютере это может сократить время создания контекста с 40 мс до менее чем 2 мс. На среднем мобильном телефоне разница может составлять от 270 мс до 10 мс.

Приложения, отличные от Chrome, которые используют V8, могут требовать больше, чем стандартный Javascript. Многие загружают дополнительные библиотеки при запуске перед тем, как запустится „основное“ приложение. Например, простая виртуальная машина TypeScript, основанная на V8, должна загружать компилятор TypeScript при запуске, чтобы переводить исходный код TypeScript в JavaScript на лету.

Начиная с выпуска V8 v4.3 два месяца назад, эмбеддеры могут использовать создание снимков, чтобы пропустить время загрузки, необходимое для такой инициализации. Тестовый случай для этой функции показывает, как работает этот API.

Чтобы создать снимок, мы можем вызвать v8::V8::CreateSnapshotDataBlob со встраиваемым скриптом в виде C-строки с завершающим нулем. После создания нового контекста этот скрипт компилируется и выполняется. В нашем примере мы создаем два пользовательских снимка начальной загрузки, каждый из которых определяет функции поверх встроенного функционала JavaScript.

Мы можем затем использовать v8::Isolate::CreateParams, чтобы настроить вновь создаваемую изоляцию так, чтобы она инициализировала контексты из пользовательского снимка начальной загрузки. Контексты, созданные в этой изоляции, являются точными копиями того, из которого мы сделали снимок. Определенные в снимке функции доступны без необходимости определять их снова.

Однако важно помнить об ограничениях: снимок может захватывать только кучу V8. Любое взаимодействие V8 с внешним миром недоступно при создании снимка. Такое взаимодействие включает:

  • определение и вызов API callbacks (то есть функций, созданных с помощью v8::FunctionTemplate)
  • создание типизированных массивов, так как хранилище может быть выделено вне V8

И, конечно же, значения, полученные из источников, таких как Math.random или Date.now, фиксируются после создания снимка. Они больше не являются случайными и не отражают текущее время.

Несмотря на ограничения, снимки начальной загрузки остаются отличным способом экономии времени на инициализацию. Мы можем сократить 100 мс загрузки компилятора TypeScript в нашем примере выше (на обычном настольном компьютере). Мы с нетерпением ждем, как вы сможете использовать пользовательские снимки!