Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fcbd2d2

Browse filesBrowse files
Gabriel Schulhofdevnexen
authored andcommitted
src: make --use-largepages a runtime option
Moves the option that instructs Node.js to-remap its static code to large pages from a configure-time option to a runtime option. This should make it easy to assess the performance impact of such a change without having to custom-build. Backport-PR-URL: #31063 PR-URL: #30954 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Co-authored-by: David Carlier <devnexen@gmail.com>
1 parent 54635f5 commit fcbd2d2
Copy full SHA for fcbd2d2

File tree

Expand file treeCollapse file tree

10 files changed

+101
-58
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

10 files changed

+101
-58
lines changed
Open diff view settings
Collapse file

‎configure.py‎

Copy file name to clipboardExpand all lines: configure.py
-33Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -398,17 +398,6 @@
398398
dest='with_etw',
399399
help='build with ETW (default is true on Windows)')
400400

401-
parser.add_option('--use-largepages',
402-
action='store_true',
403-
dest='node_use_large_pages',
404-
help='build with Large Pages support. This feature is supported only on Linux kernel' +
405-
'>= 2.6.38 with Transparent Huge pages enabled and FreeBSD')
406-
407-
parser.add_option('--use-largepages-script-lld',
408-
action='store_true',
409-
dest='node_use_large_pages_script_lld',
410-
help='link against the LLVM ld linker script. Implies -fuse-ld=lld in the linker flags')
411-
412401
intl_optgroup.add_option('--with-intl',
413402
action='store',
414403
dest='with_intl',
@@ -1041,28 +1030,6 @@ def configure_node(o):
10411030
else:
10421031
o['variables']['node_use_dtrace'] = 'false'
10431032

1044-
if options.node_use_large_pages and not flavor in ('linux', 'freebsd', 'mac'):
1045-
raise Exception(
1046-
'Large pages are supported only on Linux, FreeBSD and MacOS Systems.')
1047-
if options.node_use_large_pages and flavor in ('linux', 'freebsd', 'mac'):
1048-
if options.shared or options.enable_static:
1049-
raise Exception(
1050-
'Large pages are supported only while creating node executable.')
1051-
if target_arch!="x64":
1052-
raise Exception(
1053-
'Large pages are supported only x64 platform.')
1054-
if flavor == 'mac':
1055-
info('macOS server with 32GB or more is recommended')
1056-
if flavor == 'linux':
1057-
# Example full version string: 2.6.32-696.28.1.el6.x86_64
1058-
FULL_KERNEL_VERSION=os.uname()[2]
1059-
KERNEL_VERSION=FULL_KERNEL_VERSION.split('-')[0]
1060-
if KERNEL_VERSION < "2.6.38" and flavor == 'linux':
1061-
raise Exception(
1062-
'Large pages need Linux kernel version >= 2.6.38')
1063-
o['variables']['node_use_large_pages'] = b(options.node_use_large_pages)
1064-
o['variables']['node_use_large_pages_script_lld'] = b(options.node_use_large_pages_script_lld)
1065-
10661033
if options.no_ifaddrs:
10671034
o['defines'] += ['SUNOS_NO_IFADDRS']
10681035

Collapse file

‎doc/api/cli.md‎

Copy file name to clipboardExpand all lines: doc/api/cli.md
+17Lines changed: 17 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,22 @@ environment variables.
833833

834834
See `SSL_CERT_DIR` and `SSL_CERT_FILE`.
835835

836+
### `--use-largepages=mode`
837+
<!-- YAML
838+
added: REPLACEME
839+
-->
840+
841+
Re-map the Node.js static code to large memory pages at startup. If supported on
842+
the target system, this will cause the Node.js static code to be moved onto 2
843+
MiB pages instead of 4 KiB pages.
844+
845+
The following values are valid for `mode`:
846+
* `off`: No mapping will be attempted. This is the default.
847+
* `on`: If supported by the OS, mapping will be attempted. Failure to map will
848+
be ignored and a message will be printed to standard error.
849+
* `silent`: If supported by the OS, mapping will be attempted. Failure to map
850+
will be ignored and will not be reported.
851+
836852
### `--v8-options`
837853
<!-- YAML
838854
added: v0.1.3
@@ -1085,6 +1101,7 @@ Node.js options that are allowed are:
10851101
* `--track-heap-objects`
10861102
* `--unhandled-rejections`
10871103
* `--use-bundled-ca`
1104+
* `--use-largepages`
10881105
* `--use-openssl-ca`
10891106
* `--v8-pool-size`
10901107
* `--zero-fill-buffers`
Collapse file

‎doc/node.1‎

Copy file name to clipboardExpand all lines: doc/node.1
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,16 @@ See
371371
and
372372
.Ev SSL_CERT_FILE .
373373
.
374+
.It Fl -use-largepages Ns = Ns Ar mode
375+
Re-map the Node.js static code to large memory pages at startup. If supported on
376+
the target system, this will cause the Node.js static code to be moved onto 2
377+
MiB pages instead of 4 KiB pages.
378+
.Pp
379+
.Ar mode
380+
must have one of the following values:
381+
`off` (the default value, meaning do not map), `on` (map and ignore failure,
382+
reporting it to stderr), or `silent` (map and silently ignore failure).
383+
.
374384
.It Fl -v8-options
375385
Print V8 command-line options.
376386
.
Collapse file

‎node.gyp‎

Copy file name to clipboardExpand all lines: node.gyp
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,10 +824,9 @@
824824
}],
825825
],
826826
}],
827-
[ 'node_use_large_pages=="true" and OS in "linux freebsd mac"', {
827+
[ 'OS in "linux freebsd mac" and '
828+
'target_arch=="x64"', {
828829
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
829-
# The current implementation of Large Pages is under Linux.
830-
# Other implementations are possible but not currently supported.
831830
'sources': [
832831
'src/large_pages/node_large_page.cc',
833832
'src/large_pages/node_large_page.h'
Collapse file

‎node.gypi‎

Copy file name to clipboardExpand all lines: node.gypi
+2-4Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,17 +302,15 @@
302302
}],
303303
[ 'OS=="linux" and '
304304
'target_arch=="x64" and '
305-
'node_use_large_pages=="true" and '
306-
'node_use_large_pages_script_lld=="false"', {
305+
'llvm_version=="0.0"', {
307306
'ldflags': [
308307
'-Wl,-T',
309308
'<!(realpath src/large_pages/ld.implicit.script)',
310309
]
311310
}],
312311
[ 'OS=="linux" and '
313312
'target_arch=="x64" and '
314-
'node_use_large_pages=="true" and '
315-
'node_use_large_pages_script_lld=="true"', {
313+
'llvm_version!="0.0"', {
316314
'ldflags': [
317315
'-Wl,-T',
318316
'<!(realpath src/large_pages/ld.implicit.script.lld)',
Collapse file

‎src/large_pages/node_large_page.cc‎

Copy file name to clipboardExpand all lines: src/large_pages/node_large_page.cc
+11-8Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
// Map a new area and copy the original code there
6363
// Use mmap using the start address with MAP_FIXED so we get exactly the
6464
// same virtual address
65-
// Use madvise with MADV_HUGE_PAGE to use Anonymous 2M Pages
65+
// Use madvise with MADV_HUGEPAGE to use Anonymous 2M Pages
6666
// If successful copy the code there and unmap the original region.
6767

6868
extern char __nodetext;
@@ -308,7 +308,7 @@ static bool IsSuperPagesEnabled() {
308308
// a. map a new area and copy the original code there
309309
// b. mmap using the start address with MAP_FIXED so we get exactly
310310
// the same virtual address (except on macOS).
311-
// c. madvise with MADV_HUGE_PAGE
311+
// c. madvise with MADV_HUGEPAGE
312312
// d. If successful copy the code there and unmap the original region
313313
int
314314
#if !defined(__APPLE__)
@@ -333,9 +333,6 @@ MoveTextRegionToLargePages(const text_region& r) {
333333
PrintSystemError(errno);
334334
return -1;
335335
}
336-
OnScopeLeave munmap_on_return([nmem, size]() {
337-
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
338-
});
339336

340337
memcpy(nmem, r.from, size);
341338

@@ -352,13 +349,14 @@ MoveTextRegionToLargePages(const text_region& r) {
352349
return -1;
353350
}
354351

355-
ret = madvise(tmem, size, MADV_HUGEPAGE);
352+
ret = madvise(tmem, size, 14 /* MADV_HUGEPAGE */);
356353
if (ret == -1) {
357354
PrintSystemError(errno);
358355
ret = munmap(tmem, size);
359356
if (ret == -1) {
360357
PrintSystemError(errno);
361358
}
359+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
362360
return -1;
363361
}
364362
memcpy(start, nmem, size);
@@ -369,6 +367,7 @@ MoveTextRegionToLargePages(const text_region& r) {
369367
MAP_ALIGNED_SUPER, -1 , 0);
370368
if (tmem == MAP_FAILED) {
371369
PrintSystemError(errno);
370+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
372371
return -1;
373372
}
374373
#elif defined(__APPLE__)
@@ -383,6 +382,7 @@ MoveTextRegionToLargePages(const text_region& r) {
383382
VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
384383
if (tmem == MAP_FAILED) {
385384
PrintSystemError(errno);
385+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
386386
return -1;
387387
}
388388
memcpy(tmem, nmem, size);
@@ -393,6 +393,7 @@ MoveTextRegionToLargePages(const text_region& r) {
393393
if (ret == -1) {
394394
PrintSystemError(errno);
395395
}
396+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
396397
return -1;
397398
}
398399
memcpy(start, tmem, size);
@@ -405,8 +406,10 @@ MoveTextRegionToLargePages(const text_region& r) {
405406
if (ret == -1) {
406407
PrintSystemError(errno);
407408
}
409+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
408410
return -1;
409411
}
412+
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
410413
return ret;
411414
}
412415

@@ -418,12 +421,12 @@ int MapStaticCodeToLargePages() {
418421
return -1;
419422
}
420423

421-
#if defined(__linux__)
424+
#if defined(__linux__) || defined(__FreeBSD__)
422425
if (r.from > reinterpret_cast<void*>(&MoveTextRegionToLargePages))
423426
return MoveTextRegionToLargePages(r);
424427

425428
return -1;
426-
#elif defined(__FreeBSD__) || defined(__APPLE__)
429+
#elif defined(__APPLE__)
427430
return MoveTextRegionToLargePages(r);
428431
#endif
429432
}
Collapse file

‎src/node.cc‎

Copy file name to clipboardExpand all lines: src/node.cc
+20-10Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@
6464
#include "inspector/worker_inspector.h" // ParentInspectorHandle
6565
#endif
6666

67-
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
6867
#include "large_pages/node_large_page.h"
69-
#endif
7068

7169
#ifdef NODE_REPORT
7270
#include "node_report.h"
@@ -887,14 +885,6 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
887885

888886
CHECK_GT(argc, 0);
889887

890-
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
891-
if (node::IsLargePagesEnabled()) {
892-
if (node::MapStaticCodeToLargePages() != 0) {
893-
fprintf(stderr, "Reverting to default page size\n");
894-
}
895-
}
896-
#endif
897-
898888
// Hack around with the argv pointer. Used for process.title = "blah".
899889
argv = uv_setup_args(argc, argv);
900890

@@ -914,6 +904,26 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
914904
}
915905
}
916906

907+
#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
908+
if (per_process::cli_options->use_largepages == "on" ||
909+
per_process::cli_options->use_largepages == "silent") {
910+
if (node::IsLargePagesEnabled()) {
911+
if (node::MapStaticCodeToLargePages() != 0 &&
912+
per_process::cli_options->use_largepages != "silent") {
913+
fprintf(stderr,
914+
"Mapping code to large pages failed. Reverting to default page "
915+
"size.\n");
916+
}
917+
} else if (per_process::cli_options->use_largepages != "silent") {
918+
fprintf(stderr, "Large pages are not enabled.\n");
919+
}
920+
}
921+
#else
922+
if (per_process::cli_options->use_largepages == "on") {
923+
fprintf(stderr, "Mapping to large pages is not supported.\n");
924+
}
925+
#endif // NODE_ENABLE_LARGE_CODE_PAGES
926+
917927
if (per_process::cli_options->print_version) {
918928
printf("%s\n", NODE_VERSION);
919929
result.exit_code = 0;
Collapse file

‎src/node_options.cc‎

Copy file name to clipboardExpand all lines: src/node_options.cc
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) {
6363
"used, not both");
6464
}
6565
#endif
66+
if (use_largepages != "off" &&
67+
use_largepages != "on" &&
68+
use_largepages != "silent") {
69+
errors->push_back("invalid value for --use-largepages");
70+
}
6671
per_isolate->CheckOptions(errors);
6772
}
6873

@@ -745,6 +750,10 @@ PerProcessOptionsParser::PerProcessOptionsParser(
745750
kAllowedInEnvironment);
746751
#endif
747752
#endif
753+
AddOption("--use-largepages",
754+
"Map the Node.js static code to large pages",
755+
&PerProcessOptions::use_largepages,
756+
kAllowedInEnvironment);
748757

749758
// v12.x backwards compat flags removed in V8 7.9.
750759
AddOption("--fast_calls_with_arguments_mismatches", "", NoOp{});
Collapse file

‎src/node_options.h‎

Copy file name to clipboardExpand all lines: src/node_options.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ class PerProcessOptions : public Options {
231231
bool force_fips_crypto = false;
232232
#endif
233233
#endif
234+
std::string use_largepages = "off";
234235

235236
#ifdef NODE_REPORT
236237
std::vector<std::string> cmdline;
Collapse file
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
// Make sure that Node.js runs correctly with the --use-largepages option.
4+
5+
require('../common');
6+
const assert = require('assert');
7+
const { spawnSync } = require('child_process');
8+
9+
{
10+
const child = spawnSync(process.execPath,
11+
[ '--use-largepages=on', '-p', '42' ]);
12+
const stdout = child.stdout.toString().match(/\S+/g);
13+
assert.strictEqual(child.status, 0);
14+
assert.strictEqual(child.signal, null);
15+
assert.strictEqual(stdout.length, 1);
16+
assert.strictEqual(stdout[0], '42');
17+
}
18+
19+
{
20+
const child = spawnSync(process.execPath,
21+
[ '--use-largepages=xyzzy', '-p', '42' ]);
22+
assert.strictEqual(child.status, 9);
23+
assert.strictEqual(child.signal, null);
24+
assert.strictEqual(child.stderr.toString().match(/\S+/g).slice(1).join(' '),
25+
'invalid value for --use-largepages');
26+
}
27+
28+
// TODO(gabrielschulhof): Make assertions about the stderr, which may or may not
29+
// contain a message indicating that mapping to large pages has failed.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.