node/tools/snapshot
Anna Henningsen f99f5d3c01
src: add detailed embedder process initialization API
So far, process initialization has been a bit all over the place
in Node.js. `InitializeNodeWithArgs()` is our main public API
for this, but inclusion of items in it vs. `InitializeOncePerProcess()`
and `PlatformInit()` has been random at best. Likewise,
some pieces of initialization have been guarded by
`NODE_SHARED_MODE`, but also fairly randomly and without
any meaningful connection to shared library usage.

This leaves embedders in a position to cherry-pick some of
the initialization code into their own code to make their
application behave like typical Node.js applications to the
degree to which they desire it.

Electron takes an alternative route and makes direct use of
`InitializeOncePerProcess()` already while it is a private
API, with a `TODO` to add it to the public API in Node.js.

This commit addresses that `TODO`, and `TODO`s around the
`NODE_SHARED_MODE` usage. Specifically:

- `InitializeOncePerProcess()` and `TearDownOncePerProcess()`
  are added to the public API.
- The `flags` option of these functions are merged with the
  `flags` option for `InitializeNodeWithArgs()`, since they
  essentially share the same semantics.
- The return value of the function is made an abstract class,
  rather than a struct, for easier API/ABI stability.
- Initialization code from `main()` is brought into these
  functions (since that makes sense in general).
- Add a `TODO` for turning `InitializeNodeWithArgs()` into
  a small wrapper around `InitializeOncePerProcess()` and
  eventually removing it (at least one major release cycle
  each, presumably).
- Remove `NODE_SHARED_MODE` guards and replace them with
  runtime options.

PR-URL: https://github.com/nodejs/node/pull/44121
Backport-PR-URL: https://github.com/nodejs/node/pull/44358
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
2022-10-04 11:39:51 +01:00
..
node_mksnapshot.cc src: add detailed embedder process initialization API 2022-10-04 11:39:51 +01:00
README.md bootstrap: use SnapshotData to pass snapshot data around 2022-03-23 20:20:14 +08:00

Node.js startup snapshot builder

This is the V8 startup snapshot builder of Node.js. Not to be confused with V8's own snapshot builder, which builds a snapshot containing JavaScript builtins, this builds a snapshot containing Node.js builtins that can be deserialized on top of V8's own startup snapshot. When Node.js is launched, instead of executing code to bootstrap, it can deserialize the context from an embedded snapshot, which readily contains the result of the bootstrap, so that Node.js can start up faster.

Currently only the main context of the main Node.js instance supports snapshot deserialization, and the snapshot does not yet cover the entire bootstrap process. Work is being done to expand the support.

How it's built and used

The snapshot builder is built with the node_mksnapshot target in node.gyp when node_use_node_snapshot is set to true, which is currently done by default.

In the default build of the Node.js executable, to embed a V8 startup snapshot into the Node.js executable, libnode is first built with these unresolved symbols:

  • node::NodeMainInstance::GetEmbeddedSnapshotData

Then the node_mksnapshot executable is built with C++ files in this directory, as well as src/node_snapshot_stub.cc which defines the unresolved symbols.

node_mksnapshot is run to generate a C++ file <(SHARED_INTERMEDIATE_DIR)/node_snapshot.cc that is similar to src/node_snapshot_stub.cc in structure, but contains the snapshot data written as static char array literals. Then libnode is built with node_snapshot.cc to produce the final Node.js executable with the snapshot data embedded.

For debugging, Node.js can be built without Node.js's own snapshot if --without-node-snapshot is passed to configure. A Node.js executable with Node.js snapshot embedded can also be launched without deserializing from it if the command line argument --no-node-snapshot is passed.