Skip to content

Conversation

@joyeecheung
Copy link
Member

@joyeecheungjoyeecheung commented Feb 24, 2023

Refs: nodejs/single-executable#57

This patch adds snapshot support to single executable applications.
To build a snapshot from the main script when preparing the
blob that will be injected into the single executable application,
add "useSnapshot": true to the configuration passed to
--experimental-sea-config. For example:

{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } 

The main script used to build the snapshot must invoke
v8.startupSnapshot.setDeserializeMainFunction() to configure the
entry point. The generated startup snapshot would be part of the
preparation blob and get injected into the final executable.

When the single executable application is launched, instead of running
the main script from scratch, Node.js would instead deserialize the
snapshot to get to the state initialized during build-time directly.

$ /path/to/node --experimental-sea-config sea-config.json $ cp /path/to/node sea $ postject sea NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 $ ./sea 

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/startup

@nodejs-github-botnodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Feb 24, 2023
@RaisinTen
Copy link
Member

Thanks for doing this!

add some tooling to process the inputs

I personally really like this approach. I've opened a discussion in nodejs/single-executable#58, so that we can have a decision on this.

@RaisinTenRaisinTen added the single-executable Issues and PRs related to single-executable applications label May 12, 2023
@joyeecheungjoyeecheung changed the title POC: snapshot support in single executable applicationssea: snapshot support in single executable applicationsJun 10, 2023
@joyeecheung
Copy link
MemberAuthor

Rebased using the new SnapshotBuilder::Generate() overload added in #48242 and added a test. Will add more doc and tests next week but the implementation is there.

@piranna
Copy link
Contributor

Rebased using the new SnapshotBuilder::Generate() overload added in #48242 and added a test. Will add more doc and tests next week but the implementation is there.

What's the difference between snapshot and code cache (bytenode)?

@nodejs-github-bot

This comment was marked as outdated.

@joyeecheung
Copy link
MemberAuthor

joyeecheung commented Jun 14, 2023

What's the difference between snapshot and code cache (bytenode)?

If you have a bunch of top level code with a bunch of inner functions, usually when building the snapshot you run all the top level code and compile some of the inner functions, the snapshot contains the state of the heap after the top-level code is run and the bytecode of the inner functions that would be run again later. When deserializing the snapshot, you deserialize the state of an initialized heap (so there is no need to run the top-level code at all), and maybe later when the application invokes some of the inner functions, V8 deserialize the bytecode in the snapshot during the compilation of the function to speed things up. If there's just the code cache, what usually happens is that you have the bytecode of the top-level code and some inner functions. At runtime V8 deserializes the bytecode in the code cache to speed up compilation of the top-level code, but it still needs to run the top-level code to set up the heap.

@nodejs-github-bot

This comment was marked as outdated.

@nodejs-github-bot
Copy link
Collaborator

@joyeecheungjoyeecheung marked this pull request as ready for review June 14, 2023 15:22
@joyeecheung
Copy link
MemberAuthor

CI is almost green (with some flakes that look irrelevant). Can I have some reviews please? @nodejs/single-executable thanks!

@piranna
Copy link
Contributor

If you have a bunch of top level code with a bunch of inner functions, usually when building the snapshot you run all the top level code and compile some of the inner functions, the snapshot contains the state of the heap after the top-level code is run and the bytecode of the inner functions that would be run again later. When deserializing the snapshot, you deserialize the state of an initialized heap (so there is no need to run the top-level code at all), and maybe later when the application invokes some of the inner functions, V8 deserialize the bytecode in the snapshot during the compilation of the function to speed things up. If there's just the code cache, what usually happens is that you have the bytecode of the top-level code and some inner functions. At runtime V8 deserializes the bytecode in the code cache to speed up compilation of the top-level code, but it still needs to run the top-level code to set up the heap.

Thank you @joyeecheung for your detailed explain :-) So, if I understood it correctly, a snapshoot is a combo of a module compiled and bytecode functions plus heap after executing the module top level code, while the code cache only have the bytecode of all the module code, isn't it?

@joyeecheung
Copy link
MemberAuthor

So, if I understood it correctly, a snapshoot is a combo of a module compiled and bytecode functions plus heap after executing the module top level code, while the code cache only have the bytecode of all the module code, isn't it?

Roughly yes. V8 does not always emit bytecode for all the code it encounters (e.g. inner-inner functions are usually just parsed for syntax checks, but no bytecode is generated until they actually get executed). In some cases snapshots may contain more bytecode if during the snapshot building cases these functions are invoked.

@piranna
Copy link
Contributor

V8 does not always emit bytecode for all the code it encounters

Maybe bytenode is forcing its generation? Could it of our interest when generating the snapshots, so no Javascript code is included in it?

Copy link
Member

@benjamingrbenjamingr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@benjamingr
Copy link
Member

@RaisenTen can you please confirm you are comfortable with this based on nodejs/single-executable#58 and nodejs/single-executable#58 (reply in thread) landing

@joyeecheung
Copy link
MemberAuthor

joyeecheung commented Jun 15, 2023

Could it of our interest when generating the snapshots, so no Javascript code is included in it?

I would say that's not always a win, you could also have a lot of dead code in that application, or code that never gets run in many use cases, then eagerly generating code may result in a memory/size overhead that's not always worth it. As a configurable thing that might be useful though.

@RaisinTen
Copy link
Member

I can try to take a look day after tomorrow. (I'll be traveling pretty much the entire day tomorrow)

@piranna
Copy link
Contributor

As a configurable thing that might be useful though.

Agree on that 👍🏻

@nodejs-github-bot
Copy link
Collaborator

@joyeecheungjoyeecheung added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Jul 20, 2023
@nodejs-github-botnodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Jul 20, 2023
@nodejs-github-bot
Copy link
Collaborator

Commit Queue failed
- Loading data for nodejs/node/pull/46824 ✔ Done loading data for nodejs/node/pull/46824 ----------------------------------- PR info ------------------------------------ Title sea: snapshot support in single executable applications (#46824) Author Joyee Cheung (@joyeecheung) Branch joyeecheung:sea-snapshot -> nodejs:main Labels c++, lib / src, needs-ci, commit-queue-squash, single-executable Commits 4 - src: support snapshot in single executable applications - fixup! src: support snapshot in single executable applications - fixup! fixup! src: support snapshot in single executable applications - fixup! fixup! fixup! src: support snapshot in single executable appli… Committers 1 - Joyee Cheung PR-URL: https://github.com/nodejs/node/pull/46824 Refs: https://github.com/nodejs/single-executable/discussions/57 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Darshan Sen ------------------------------ Generated metadata ------------------------------ PR-URL: https://github.com/nodejs/node/pull/46824 Refs: https://github.com/nodejs/single-executable/discussions/57 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Darshan Sen -------------------------------------------------------------------------------- ℹ This PR was created on Fri, 24 Feb 2023 18:28:13 GMT ✔ Approvals: 2 ✔ - Benjamin Gruenbaum (@benjamingr) (TSC): https://github.com/nodejs/node/pull/46824#pullrequestreview-1482036842 ✔ - Darshan Sen (@RaisinTen) (TSC): https://github.com/nodejs/node/pull/46824#pullrequestreview-1538950503 ✘ Last GitHub CI failed ℹ Last Full PR CI on 2023-07-20T18:44:40Z: https://ci.nodejs.org/job/node-test-pull-request/52874/ - Querying data for job/node-test-pull-request/52874/ ✔ Last Jenkins CI successful -------------------------------------------------------------------------------- ✔ Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/5615590467

@joyeecheungjoyeecheung added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. labels Jul 20, 2023
@nodejs-github-botnodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Jul 20, 2023
@nodejs-github-botnodejs-github-bot merged commit ac34e75 into nodejs:mainJul 20, 2023
@nodejs-github-bot
Copy link
Collaborator

Landed in ac34e75

### Startup snapshot support
The `useSnapshot` field can be used to enable startup snapshot support. In this
case the `main` script would not be when the final executable is launched.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's missing a run: "would not be run"

rluvaton pushed a commit to rluvaton/node that referenced this pull request Jul 21, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
pluris pushed a commit to pluris/node that referenced this pull request Aug 6, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
pluris pushed a commit to pluris/node that referenced this pull request Aug 7, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
UlisesGascon pushed a commit to UlisesGascon/node that referenced this pull request Aug 14, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: nodejs#46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
RafaelGSS pushed a commit that referenced this pull request Aug 15, 2023
This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ```{"main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: #46824 Refs: nodejs/single-executable#57 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
@UlisesGasconUlisesGascon mentioned this pull request Aug 15, 2023
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.commit-queue-squashAdd this label to instruct the Commit Queue to squash all the PR commits into the first one.lib / srcIssues and PRs related to general changes in the lib or src directory.needs-ciPRs that need a full CI run.single-executableIssues and PRs related to single-executable applications

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@joyeecheung@nodejs-github-bot@RaisinTen@piranna@benjamingr@aymen94