Uh oh!
There was an error while loading. Please reload this page.
bootstrap: implement run-time user-land snapshots via --build-snapshot and --snapshot-blob - #38905
bootstrap: implement run-time user-land snapshots via --build-snapshot and --snapshot-blob#38905joyeecheung wants to merge 6 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
bl-ue
commented
Jun 2, 2021
Wow, that's really cool. Can't wait! ❤️ |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
targos
commented
Jun 2, 2021
What is the compatibility of the snapshot blob WRT V8/Node version, other CLI flags, etc? |
targos
commented
Jun 2, 2021
And what happens if you try to load a snapshot with the wrong version of the runtime? |
@targos The blob requires the version of V8/Node to be the same between build time and load time - V8 checks the versions explicitly, and abort if there is a mismatch, while at the moment Node.js should work as long as the number/kind/order of external references etc. match between the binaries used to build and load the snapshot (what happens when there is a mismatch depends on what the mismatch actually is, I would say it's most likely that the process would abort when some V8 casting type check fails e.g. casting e.g. a String to a Function, because one version expects value at blob index n to be a String and the other expects value at blob index n to be a Function). Maybe we could explicitly check the Node.js versions as well so when there is a mismatch users can understand what's wrong immediately. The CLI flags can vary between between build time and load time, to some extent, it depends on the actual flags being used. |
targos
commented
Jun 3, 2021
Seems like a good idea. |
joyeecheung
commented
Jun 3, 2021
Also that reminded me that we need to regenerate |
Another thing that we need to watch out for: right now some modules cache access to |
addaleax
commented
Jun 10, 2021
Fwiw, I think it’s generally a good idea not to cache these values, so that they become configurable – independently of snapshot support. |
joyeecheung
commented
Jun 10, 2021
At the source code level I agree - not caching it directly via the form of something like |
Updated the prototype a bit, now it loads the snapshot entry point from JS (the snapshot would only be generated when it runs to completion), this gives us more control in e.g. warning about unsupported modules. I've split some smaller commits to other PRs, there's also a small V8 debuggability thing that I'll upstream later. Some issues I discovered:
(Also, I realized that many modules just require the CJS module loader at the top level, which would in turn require the ESM loader at the top level, which leaves a promise immediately. Not sure how to work around that promise yet but I guess for now we could just make sure that other modules only load those loaders when they actually need to...) |
jasnell
commented
Jun 11, 2021
It's likely worth opening a separate issue for this particular piece. I agree that getting away from caching as a module-scope |
This is only necessary for the snapshot builder (because we have no way to resurrect the handles at the moment). In addition, print the handles if the debug flag is set or if the queues are not empty after snapshot is created. PR-URL: #39007 Refs: #35711 Refs: #38905 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This is only necessary for the snapshot builder (because we have no way to resurrect the handles at the moment). In addition, print the handles if the debug flag is set or if the queues are not empty after snapshot is created. PR-URL: #39007 Refs: #35711 Refs: #38905 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This way, internal modules can still require the module and cache the function getOptionValue() early (therefore these code can be included in the snapshots), but the options map won't be serialized from C++ land until the option values are actually queried. PR-URL: #38993 Refs: #35711 Refs: #38905 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Zijian Liu <lxxyxzj@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
3ae6d68 to
28f6becComparePR-URL: nodejs#38905 Refs: nodejs#35711 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
nodejs-github-bot
commented
Aug 2, 2022
joyeecheung
commented
Aug 2, 2022
Added two more fixups to accommodate recent changes:
cc @legendecas@mcollina (feel free to ignore) still LGTY? |
nodejs-github-bot
commented
Aug 2, 2022
legendecas
commented
Aug 2, 2022
You may need to format the code. |
joyeecheung
commented
Aug 2, 2022
Landed with |
Note to releasers: this needs to be backported after the two PRs mentioned above #38905 (comment) or there would be conflicts |
danielleadams
commented
Aug 16, 2022
@joyeecheung#43984 needs a backport, so I'm going to mark this as |
ruyadorno
commented
Aug 22, 2022
It looks like #44203 builds on top of this PR, so I'm marking it with the |
ruyadorno
commented
Aug 23, 2022
That worked! thanks @joyeecheung! Removing the |
gajus
commented
Aug 27, 2022
Where can I track progress of this? |
joyeecheung
commented
Aug 29, 2022
@gajus The SEA effort is tracked in https://github.com/nodejs/single-executable and currently most activities take place in https://github.com/nodejs/single-executable/discussions |
This patch introduces
--build-snapshotand--snapshot-bloboptions for creating and using user land snapshots.For the initial iteration, user land CJS modules and ESM are not yet supported in the snapshot, so only one single file can be snapshotted (users can bundle their applications into a single script with their bundler of choice to build a snapshot though).
A subset of builtins should already work, and support for more builtins are being added. This PR includes tests checking that the TypeScript compiler and the marked markdown renderer (and the builtins they use) can be snapshotted and deserialized.
To generate a snapshot using
snapshot.jsas entry point and write the snapshot blob tosnapshot.blob:To restore application state from
snapshot.blob, withindex.jsas the entry point script for the deserialized application:Users can also use the
v8.startupSnapshotAPI to specify an entry point at snapshot building time, thus avoiding the need of an additional entry script at deserialization time:Note that this patch only adds functionality to the
nodeexecutable for building run-time user-land snapshots, the generated snapshot is stored into a separate file on disk. Building a single binary with both Node.js and an embedded snapshot has already been possible with the--node-snapshot-mainoption to theconfigurescript if the user compiles Node.js from source. It would be a different task to enable thenodeexecutable to produce a single binary that contains both Node.js and an embedded snapshot without building Node.js from source, which should be layered on top of the SEA (Single Executable Apps) initiative.Known limitations/bugs that are being fixed in the V8 upstream:
Error.stackTraceLimit(it should work fine in the release build, however): https://chromium-review.googlesource.com/c/v8/v8/+/3319481More known limitations/bugs in the tracking issue: #44014
Refs: #35711