Skip to content

Commit a83c5df

Browse files
author
Gabriel Schulhof
committed
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.
1 parent d06efaf commit a83c5df

10 files changed

+53
-51
lines changed

configure.py

-33
Original file line numberDiff line numberDiff line change
@@ -404,17 +404,6 @@
404404
dest='with_etw',
405405
help='build with ETW (default is true on Windows)')
406406

407-
parser.add_option('--use-largepages',
408-
action='store_true',
409-
dest='node_use_large_pages',
410-
help='build with Large Pages support. This feature is supported only on Linux kernel' +
411-
'>= 2.6.38 with Transparent Huge pages enabled and FreeBSD')
412-
413-
parser.add_option('--use-largepages-script-lld',
414-
action='store_true',
415-
dest='node_use_large_pages_script_lld',
416-
help='link against the LLVM ld linker script. Implies -fuse-ld=lld in the linker flags')
417-
418407
intl_optgroup.add_option('--with-intl',
419408
action='store',
420409
dest='with_intl',
@@ -1068,28 +1057,6 @@ def configure_node(o):
10681057
else:
10691058
o['variables']['node_use_dtrace'] = 'false'
10701059

1071-
if options.node_use_large_pages and not flavor in ('linux', 'freebsd', 'mac'):
1072-
raise Exception(
1073-
'Large pages are supported only on Linux, FreeBSD and MacOS Systems.')
1074-
if options.node_use_large_pages and flavor in ('linux', 'freebsd', 'mac'):
1075-
if options.shared or options.enable_static:
1076-
raise Exception(
1077-
'Large pages are supported only while creating node executable.')
1078-
if target_arch!="x64":
1079-
raise Exception(
1080-
'Large pages are supported only x64 platform.')
1081-
if flavor == 'mac':
1082-
info('macOS server with 32GB or more is recommended')
1083-
if flavor == 'linux':
1084-
# Example full version string: 2.6.32-696.28.1.el6.x86_64
1085-
FULL_KERNEL_VERSION=os.uname()[2]
1086-
KERNEL_VERSION=FULL_KERNEL_VERSION.split('-')[0]
1087-
if KERNEL_VERSION < "2.6.38" and flavor == 'linux':
1088-
raise Exception(
1089-
'Large pages need Linux kernel version >= 2.6.38')
1090-
o['variables']['node_use_large_pages'] = b(options.node_use_large_pages)
1091-
o['variables']['node_use_large_pages_script_lld'] = b(options.node_use_large_pages_script_lld)
1092-
10931060
if options.no_ifaddrs:
10941061
o['defines'] += ['SUNOS_NO_IFADDRS']
10951062

doc/api/cli.md

+10
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,15 @@ environment variables.
863863

864864
See `SSL_CERT_DIR` and `SSL_CERT_FILE`.
865865

866+
### `--use-largepages`
867+
<!-- YAML
868+
added: REPLACEME
869+
-->
870+
871+
Re-map the Node.js static code to large memory pages at startup. If supported on
872+
the target system, this will cause the Node.js static code to be moved onto 2
873+
MiB pages instead of 4 KiB pages.
874+
866875
### `--v8-options`
867876
<!-- YAML
868877
added: v0.1.3
@@ -1119,6 +1128,7 @@ Node.js options that are allowed are:
11191128
* `--track-heap-objects`
11201129
* `--unhandled-rejections`
11211130
* `--use-bundled-ca`
1131+
* `--use-largepages`
11221132
* `--use-openssl-ca`
11231133
* `--v8-pool-size`
11241134
* `--zero-fill-buffers`

doc/node.1

+5
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,11 @@ See
398398
and
399399
.Ev SSL_CERT_FILE .
400400
.
401+
.It Fl -use-largepages
402+
Re-map the Node.js static code to large memory pages at startup. If supported on
403+
the target system, this will cause the Node.js static code to be moved onto 2
404+
MiB pages instead of 4 KiB pages.
405+
.
401406
.It Fl -v8-options
402407
Print V8 command-line options.
403408
.

node.gyp

+1-1
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@
833833
}],
834834
],
835835
}],
836-
[ 'node_use_large_pages=="true" and OS in "linux freebsd mac"', {
836+
[ 'OS in "linux freebsd mac"', {
837837
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
838838
# The current implementation of Large Pages is under Linux.
839839
# Other implementations are possible but not currently supported.

node.gypi

+2-4
Original file line numberDiff line numberDiff line change
@@ -308,17 +308,15 @@
308308
}],
309309
[ 'OS=="linux" and '
310310
'target_arch=="x64" and '
311-
'node_use_large_pages=="true" and '
312-
'node_use_large_pages_script_lld=="false"', {
311+
'llvm_version=="0.0"', {
313312
'ldflags': [
314313
'-Wl,-T',
315314
'<!(realpath src/large_pages/ld.implicit.script)',
316315
]
317316
}],
318317
[ 'OS=="linux" and '
319318
'target_arch=="x64" and '
320-
'node_use_large_pages=="true" and '
321-
'node_use_large_pages_script_lld=="true"', {
319+
'llvm_version!="0.0"', {
322320
'ldflags': [
323321
'-Wl,-T',
324322
'<!(realpath src/large_pages/ld.implicit.script.lld)',

src/large_pages/node_large_page.cc

+3-3
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__)
@@ -352,7 +352,7 @@ MoveTextRegionToLargePages(const text_region& r) {
352352
return -1;
353353
}
354354

355-
ret = madvise(tmem, size, MADV_HUGEPAGE);
355+
ret = madvise(tmem, size, 14 /* MADV_HUGEPAGE */);
356356
if (ret == -1) {
357357
PrintSystemError(errno);
358358
ret = munmap(tmem, size);

src/node.cc

+8-10
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"
@@ -967,14 +965,6 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
967965

968966
CHECK_GT(argc, 0);
969967

970-
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
971-
if (node::IsLargePagesEnabled()) {
972-
if (node::MapStaticCodeToLargePages() != 0) {
973-
fprintf(stderr, "Reverting to default page size\n");
974-
}
975-
}
976-
#endif
977-
978968
// Hack around with the argv pointer. Used for process.title = "blah".
979969
argv = uv_setup_args(argc, argv);
980970

@@ -994,6 +984,14 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
994984
}
995985
}
996986

987+
if (per_process::cli_options->use_largepages) {
988+
if (node::IsLargePagesEnabled()) {
989+
if (node::MapStaticCodeToLargePages() != 0) {
990+
fprintf(stderr, "Reverting to default page size\n");
991+
}
992+
}
993+
}
994+
997995
if (per_process::cli_options->print_version) {
998996
printf("%s\n", NODE_VERSION);
999997
result.exit_code = 0;

src/node_options.cc

+4
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,10 @@ PerProcessOptionsParser::PerProcessOptionsParser(
748748
kAllowedInEnvironment);
749749
#endif
750750
#endif
751+
AddOption("--use-largepages",
752+
"Map the Node.js static code to large pages",
753+
&PerProcessOptions::use_largepages,
754+
kAllowedInEnvironment);
751755

752756
Insert(iop, &PerProcessOptions::get_per_isolate_options);
753757
}

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ class PerProcessOptions : public Options {
235235
bool force_fips_crypto = false;
236236
#endif
237237
#endif
238+
bool use_largepages = false;
238239

239240
#ifdef NODE_REPORT
240241
std::vector<std::string> cmdline;
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
// A sanity check: Make sure that Node.js runs correctly when running with the
4+
// --use-largepages option.
5+
6+
require('../common');
7+
const assert = require('assert');
8+
const { spawnSync } = require('child_process');
9+
10+
const child = spawnSync(process.execPath, [ '--use-largepages', '-p', '42' ]);
11+
const stdout = child.stdout.toString().match(/\S+/g);
12+
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+
// TODO(gabrielschulhof): Make assertions about the stderr, which may or may not
19+
// contain a message indicating that mapping to large pages has failed.

0 commit comments

Comments
 (0)