Node.js/v8: Как сделать собственный снимок для ускорения запуска

У меня есть приложение node.js (v0.6.12), которое запускается с оценки файла Javascript, startup.js. Оценка startup.js занимает много времени, и я хотел бы «запечь» его в пользовательской сборке Node, если это возможно.

Исходный каталог v8, распространяемый вместе с Node, node/deps/v8/src, содержит SconScript, который практически можно использовать для этого. В строке 302 имеем

LIBRARY_FILES = '''
runtime.js
v8natives.js
array.js
string.js
uri.js
math.js
messages.js
apinatives.js
date.js
regexp.js
json.js
liveedit-debugger.js
mirror-debugger.js
debug-debugger.js
'''.split()

Эти файлы javascript находятся в одном каталоге. Очевидно, что-то в процессе сборки оценивает их, делает снимок состояния и сохраняет его в виде строки байтов в node/out/Release/obj/release/snapshot.cc (в Mac OS). Этот файл, кажется, встроен в Node.

Возможна некоторая настройка моментального снимка запуска путем изменения файла SconScript. Например, я могу изменить определение встроенного Date.toString, изменив date.js. Я даже могу добавить новые глобальные переменные, добавив startup.js в список файлов библиотеки с содержимым global.test = 1.

Однако я не могу поместить любой код javascript в startup.js. Если он содержит Date.toString = 1;, возникает ошибка, даже если код действителен в узле repl:

Build failed:  -> task failed (err #2): 
    {task: libv8.a SConstruct -> libv8.a}
make: *** [program] Error 1

И, очевидно, он не может использовать код, зависящий от библиотек, добавленных Node в v8. global.underscore = require('underscore'); вызывает ту же ошибку.

В идеале мне нужен инструмент customSnapshot, где customSnapshot startup.js оценивает startup.js с помощью Node, а затем выгружает снимок в файл snapshot.cc, который я могу поместить в исходный каталог Node. Затем я могу построить узел и сказать ему не перестраивать моментальный снимок.


person Anand Patil    schedule 19.06.2012    source источник
comment
На самом деле этот метод отлично сработал для меня, и я использовал node.js v0.8.11, который поставляется с v8 v3.11.10. Разница в том, что я использовал новую сборку на основе gyp. Здесь вы можете увидеть необходимые изменения. Как вы сказали, вы не можете вызывать код, который зависит от встроенных объектов или функций nodejs (консоль, требование...). Вы можете обойти это, используя функцию инициализации ann: var global = this; global.initialize = function() { global.console.log('Hello node'); };   -  person Thiago de Arruda    schedule 28.09.2012


Ответы (1)


Я только что добавил параметр в команду mksnapshot (которая запускается во время сборки V8). Новый флаг --extra-file=filename.js позволяет указать файл, который нужно загрузить и запустить в процессе, а затем поместить в снимок. Это магистральная версия V8, а не ветка 3.11, которая используется для узла 0.8, поэтому вам придется запускать узел 0.8 с версией 3.11 V8. Насколько я знаю, на данный момент это работает, но вы будете в некоторой степени предоставлены сами себе.

Пожалуйста, сообщите об ошибках, если вы попробуете это, и это не сработает для вас.

person Erik Corry    schedule 20.06.2012
comment
Спасибо, user487683, у меня новый вариант работает. Для потомков ваши изменения были в этой версии: code.google.com/ p/v8/source/detail?r=11871 . Чтобы добавить дополнительный код в процесс сборки, я изменил определение env.Snapshot в строке 343 SconScript на env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE" --log-snapshot-positions --extra-code "path/to/file.js"'). Похоже, что этот файл запускается после библиотечных файлов, перечисленных в SconScript, поэтому он может изменять объекты, которые они вводят. Однако он выполняется раньше всего в Node. - person Anand Patil; 28.06.2012