Skip to content

bootstrap: optimize modules loaded in the built-in snapshot#45849

Closed
joyeecheung wants to merge 15 commits intonodejs:mainfrom
joyeecheung:lazyload2
Closed

bootstrap: optimize modules loaded in the built-in snapshot#45849
joyeecheung wants to merge 15 commits intonodejs:mainfrom
joyeecheung:lazyload2

Conversation

@joyeecheung
Copy link
Member

To make the patch easier to review I have split it into smaller commits, though it's probably also okay to review the entire diff since most of the changes are superficial.

Locally I got:

                                                                                     confidence improvement accuracy (*)   (**)  (***)
misc/startup.js count=30 mode='process' script='benchmark/fixtures/require-builtins'        ***      4.14 %       ±0.59% ±0.79% ±1.03%
misc/startup.js count=30 mode='process' script='test/fixtures/semicolon'                    ***     11.11 %       ±0.75% ±1.00% ±1.30%
misc/startup.js count=30 mode='worker' script='benchmark/fixtures/require-builtins'         ***      3.67 %       ±0.73% ±0.97% ±1.27%
misc/startup.js count=30 mode='worker' script='test/fixtures/semicolon'                     ***     10.93 %       ±0.90% ±1.20% ±1.56%

bootstrap: support module_wrap binding in snapshot

bootstrap: include event_target into the built-in snapshot

Since the module has to be loaded during bootstrap anyway.

modules: move modules/cjs/helpers.js to modules/helpers.js

The helpers are actually shared by the two loaders, so move them
under modules/ directly.

lib: add getLazy() method to internal/util

This patch adds a getLazy() method to facilitate initialize-once
lazy loading in the internals.

lib: lazy-load deps in source_map_cache.js

So that the file can be snapshotted.

lib: lazy-load deps in modules/run_main.js

So that the file can be snapshotted

modules: move callbacks and conditions into modules/esm/utils.js

This moves the following utils into modules/esm/utils.js:

  • Code related to default conditions
  • The callbackMap (which is now created in the module instead of
    hanging off the module_wrap binding, since the C++ land
    does not need it).
  • Per-isolate module callbacks

These are self-contained code that can be included into the
built-in snapshot.

bootstrap: make CJS loader snapshotable

This patch makes the top-level access to runtime states in the
CJS loader lazy, and move the side-effects into a
initializeCJS() function that gets called during pre-execution.
As a result the CJS loader can be included into the built-in
snapshot.

bootstrap: optimize modules loaded in the built-in snapshot

Preload essential modules and lazy-load non-essential ones.
After this patch, all modules listed by running this snippet:

const list = process.moduleLoadList.join('\n');
require('fs').writeSync(1, list, 'utf-8');

(which is roughly the same list as the one in
test-bootstrap-module.js for the main thread)
are loaded from the snapshot so no additional compilation cost
is incurred.

Since the module has to be loaded during bootstrap anyway.
The helpers are actually shared by the two loaders, so move them
under modules/ directly.
This patch adds a getLazy() method to facilitate initialize-once
lazy loading in the internals.
So that the file can be snapshotted.
So that the file can be snapshotted
This moves the following utils into modules/esm/utils.js:

- Code related to default conditions
- The callbackMap (which is now created in the module instead of
  hanging off the module_wrap binding, since the C++ land
  does not need it).
- Per-isolate module callbacks

These are self-contained code that can be included into the
built-in snapshot.
This patch makes the top-level access to runtime states in the
CJS loader lazy, and move the side-effects into a
initializeCJS() function that gets called during pre-execution.
As a result the CJS loader can be included into the built-in
snapshot.
Preload essential modules and lazy-load non-essential ones.
After this patch, all modules listed by running this snippet:

```
const list = process.moduleLoadList.join('\n');
require('fs').writeSync(1, list, 'utf-8');
```

(which is roughly the same list as the one in
test-bootstrap-module.js for the main thread)
are loaded from the snapshot so no additional compilation cost
is incurred.
@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/modules
  • @nodejs/startup
  • @nodejs/vm

@nodejs-github-bot nodejs-github-bot added 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 Dec 14, 2022
@nodejs-github-bot
Copy link
Collaborator

@GeoffreyBooth
Copy link
Member

What’s the relationship between this PR and #45828? Is this just the first of the several commits you mentioned?

@joyeecheung
Copy link
Member Author

@GeoffreyBooth This is a trimmed down version of #45828 that does not attempt to snapshot the ESM loader (except some really small bits)

@GeoffreyBooth
Copy link
Member

Okay, well even still this seems like a significant improvement. The benchmarks you posted here are almost as good as in #45828, so it seems like you’ve achieved the bulk of the performance boost already in this PR alone.

@joyeecheung
Copy link
Member Author

From the CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1264/

02:34:00                                                                                      confidence improvement accuracy (*)   (**)  (***)
02:34:01 misc/startup.js count=30 mode='process' script='benchmark/fixtures/require-builtins'        ***      3.32 %       ±0.84% ±1.11% ±1.45%
02:34:01 misc/startup.js count=30 mode='process' script='test/fixtures/semicolon'                    ***     10.02 %       ±1.17% ±1.57% ±2.04%
02:34:01 misc/startup.js count=30 mode='worker' script='benchmark/fixtures/require-builtins'         ***      5.03 %       ±0.90% ±1.20% ±1.56%
02:34:01 misc/startup.js count=30 mode='worker' script='test/fixtures/semicolon'                     ***     11.24 %       ±1.27% ±1.69% ±2.21%

Copy link
Member

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

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

Thanks for doing this. I can’t speak for the bootstrap parts but the module refactors look great!

@nodejs-github-bot
Copy link
Collaborator

panva pushed a commit to joyeecheung/node that referenced this pull request Jan 31, 2023
So that the file can be snapshotted.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
panva pushed a commit to joyeecheung/node that referenced this pull request Jan 31, 2023
So that the file can be snapshotted

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
panva pushed a commit to joyeecheung/node that referenced this pull request Jan 31, 2023
This moves the following utils into modules/esm/utils.js:

- Code related to default conditions
- The callbackMap (which is now created in the module instead of
  hanging off the module_wrap binding, since the C++ land
  does not need it).
- Per-isolate module callbacks

These are self-contained code that can be included into the
built-in snapshot.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
panva pushed a commit to joyeecheung/node that referenced this pull request Jan 31, 2023
This patch makes the top-level access to runtime states in the
CJS loader lazy, and move the side-effects into a
initializeCJS() function that gets called during pre-execution.
As a result the CJS loader can be included into the built-in
snapshot.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
panva pushed a commit to joyeecheung/node that referenced this pull request Jan 31, 2023
Preload essential modules and lazy-load non-essential ones.
After this patch, all modules listed by running this snippet:

```
const list = process.moduleLoadList.join('\n');
require('fs').writeSync(1, list, 'utf-8');
```

(which is roughly the same list as the one in
test-bootstrap-module.js for the main thread)
are loaded from the snapshot so no additional compilation cost
is incurred.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
@bnoordhuis
Copy link
Member

#45551 needs to be backported first

@juanarbol that's been done. This PR and #46225 should be unblocked now?

targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
Since the module has to be loaded during bootstrap anyway.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
The helpers are actually shared by the two loaders, so move them
under modules/ directly.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
This patch adds a getLazy() method to facilitate initialize-once
lazy loading in the internals.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
So that the file can be snapshotted.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
So that the file can be snapshotted

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
This moves the following utils into modules/esm/utils.js:

- Code related to default conditions
- The callbackMap (which is now created in the module instead of
  hanging off the module_wrap binding, since the C++ land
  does not need it).
- Per-isolate module callbacks

These are self-contained code that can be included into the
built-in snapshot.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
This patch makes the top-level access to runtime states in the
CJS loader lazy, and move the side-effects into a
initializeCJS() function that gets called during pre-execution.
As a result the CJS loader can be included into the built-in
snapshot.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit to joyeecheung/node that referenced this pull request Oct 28, 2023
Preload essential modules and lazy-load non-essential ones.
After this patch, all modules listed by running this snippet:

```
const list = process.moduleLoadList.join('\n');
require('fs').writeSync(1, list, 'utf-8');
```

(which is roughly the same list as the one in
test-bootstrap-module.js for the main thread)
are loaded from the snapshot so no additional compilation cost
is incurred.

PR-URL: nodejs#45849
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
codebytere added a commit to electron/electron that referenced this pull request Nov 6, 2023
codebytere added a commit to electron/electron that referenced this pull request Nov 6, 2023
targos pushed a commit that referenced this pull request Nov 10, 2023
PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit that referenced this pull request Nov 10, 2023
Since the module has to be loaded during bootstrap anyway.

PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit that referenced this pull request Nov 10, 2023
The helpers are actually shared by the two loaders, so move them
under modules/ directly.

PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit that referenced this pull request Nov 10, 2023
This patch adds a getLazy() method to facilitate initialize-once
lazy loading in the internals.

PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit that referenced this pull request Nov 10, 2023
So that the file can be snapshotted.

PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
targos pushed a commit that referenced this pull request Nov 10, 2023
So that the file can be snapshotted

PR-URL: #45849
Backport-PR-URL: #46425
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants