GeezerVison is showing github.com — src: make --use-largepages a runtime option · nodejs/node@fcbd2d2
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: configure.py -33Lines changed: 0 additions & 33 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 398 | 398 | dest='with_etw', | 399 | 399 | help='build with ETW (default is true on Windows)') | 400 | 400 |
| 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 | | - | 412 | 401 | intl_optgroup.add_option('--with-intl', | 413 | 402 | action='store', | 414 | 403 | dest='with_intl', | @@ -1041,28 +1030,6 @@ def configure_node(o): | 1041 | 1030 | else: | 1042 | 1031 | o['variables']['node_use_dtrace'] = 'false' | 1043 | 1032 |
| 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 | | - | 1066 | 1033 | if options.no_ifaddrs: | 1067 | 1034 | o['defines'] += ['SUNOS_NO_IFADDRS'] | 1068 | 1035 |
| |
Collapse file 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 number | Diff line number | Diff line change |
|---|
@@ -833,6 +833,22 @@ environment variables. | 833 | 833 |
| 834 | 834 | See `SSL_CERT_DIR` and `SSL_CERT_FILE`. | 835 | 835 |
| | 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 | + | 836 | 852 | ### `--v8-options` | 837 | 853 | <!-- YAML | 838 | 854 | added: v0.1.3 | @@ -1085,6 +1101,7 @@ Node.js options that are allowed are: | 1085 | 1101 | * `--track-heap-objects` | 1086 | 1102 | * `--unhandled-rejections` | 1087 | 1103 | * `--use-bundled-ca` | | 1104 | +* `--use-largepages` | 1088 | 1105 | * `--use-openssl-ca` | 1089 | 1106 | * `--v8-pool-size` | 1090 | 1107 | * `--zero-fill-buffers` | |
Collapse file Copy file name to clipboardExpand all lines: doc/node.1 +10Lines changed: 10 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 371 | 371 | and | 372 | 372 | .Ev SSL_CERT_FILE . | 373 | 373 | . | | 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 | +. | 374 | 384 | .It Fl -v8-options | 375 | 385 | Print V8 command-line options. | 376 | 386 | . | |
Collapse file Copy file name to clipboardExpand all lines: node.gyp +2-3Lines changed: 2 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 824 | 824 | }], | 825 | 825 | ], | 826 | 826 | }], | 827 | | - [ 'node_use_large_pages=="true" and OS in "linux freebsd mac"', { | | 827 | + [ 'OS in "linux freebsd mac" and ' | | 828 | + 'target_arch=="x64"', { | 828 | 829 | '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. | 831 | 830 | 'sources': [ | 832 | 831 | 'src/large_pages/node_large_page.cc', | 833 | 832 | 'src/large_pages/node_large_page.h' | |
Collapse file Copy file name to clipboardExpand all lines: node.gypi +2-4Lines changed: 2 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 302 | 302 | }], | 303 | 303 | [ 'OS=="linux" and ' | 304 | 304 | 'target_arch=="x64" and ' | 305 | | - 'node_use_large_pages=="true" and ' | 306 | | - 'node_use_large_pages_script_lld=="false"', { | | 305 | + 'llvm_version=="0.0"', { | 307 | 306 | 'ldflags': [ | 308 | 307 | '-Wl,-T', | 309 | 308 | '<!(realpath src/large_pages/ld.implicit.script)', | 310 | 309 | ] | 311 | 310 | }], | 312 | 311 | [ 'OS=="linux" and ' | 313 | 312 | 'target_arch=="x64" and ' | 314 | | - 'node_use_large_pages=="true" and ' | 315 | | - 'node_use_large_pages_script_lld=="true"', { | | 313 | + 'llvm_version!="0.0"', { | 316 | 314 | 'ldflags': [ | 317 | 315 | '-Wl,-T', | 318 | 316 | '<!(realpath src/large_pages/ld.implicit.script.lld)', | |
Collapse file Copy file name to clipboardExpand all lines: src/large_pages/node_large_page.cc +11-8Lines changed: 11 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 62 | 62 | // Map a new area and copy the original code there | 63 | 63 | // Use mmap using the start address with MAP_FIXED so we get exactly the | 64 | 64 | // 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 | 66 | 66 | // If successful copy the code there and unmap the original region. | 67 | 67 |
| 68 | 68 | extern char __nodetext; | @@ -308,7 +308,7 @@ static bool IsSuperPagesEnabled() { | 308 | 308 | // a. map a new area and copy the original code there | 309 | 309 | // b. mmap using the start address with MAP_FIXED so we get exactly | 310 | 310 | // the same virtual address (except on macOS). | 311 | | -// c. madvise with MADV_HUGE_PAGE | | 311 | +// c. madvise with MADV_HUGEPAGE | 312 | 312 | // d. If successful copy the code there and unmap the original region | 313 | 313 | int | 314 | 314 | #if !defined(__APPLE__) | @@ -333,9 +333,6 @@ MoveTextRegionToLargePages(const text_region& r) { | 333 | 333 | PrintSystemError(errno); | 334 | 334 | return -1; | 335 | 335 | } | 336 | | - OnScopeLeave munmap_on_return([nmem, size]() { | 337 | | - if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 338 | | - }); | 339 | 336 |
| 340 | 337 | memcpy(nmem, r.from, size); | 341 | 338 |
| @@ -352,13 +349,14 @@ MoveTextRegionToLargePages(const text_region& r) { | 352 | 349 | return -1; | 353 | 350 | } | 354 | 351 |
| 355 | | - ret = madvise(tmem, size, MADV_HUGEPAGE); | | 352 | + ret = madvise(tmem, size, 14 /* MADV_HUGEPAGE */); | 356 | 353 | if (ret == -1) { | 357 | 354 | PrintSystemError(errno); | 358 | 355 | ret = munmap(tmem, size); | 359 | 356 | if (ret == -1) { | 360 | 357 | PrintSystemError(errno); | 361 | 358 | } | | 359 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 362 | 360 | return -1; | 363 | 361 | } | 364 | 362 | memcpy(start, nmem, size); | @@ -369,6 +367,7 @@ MoveTextRegionToLargePages(const text_region& r) { | 369 | 367 | MAP_ALIGNED_SUPER, -1 , 0); | 370 | 368 | if (tmem == MAP_FAILED) { | 371 | 369 | PrintSystemError(errno); | | 370 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 372 | 371 | return -1; | 373 | 372 | } | 374 | 373 | #elif defined(__APPLE__) | @@ -383,6 +382,7 @@ MoveTextRegionToLargePages(const text_region& r) { | 383 | 382 | VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); | 384 | 383 | if (tmem == MAP_FAILED) { | 385 | 384 | PrintSystemError(errno); | | 385 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 386 | 386 | return -1; | 387 | 387 | } | 388 | 388 | memcpy(tmem, nmem, size); | @@ -393,6 +393,7 @@ MoveTextRegionToLargePages(const text_region& r) { | 393 | 393 | if (ret == -1) { | 394 | 394 | PrintSystemError(errno); | 395 | 395 | } | | 396 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 396 | 397 | return -1; | 397 | 398 | } | 398 | 399 | memcpy(start, tmem, size); | @@ -405,8 +406,10 @@ MoveTextRegionToLargePages(const text_region& r) { | 405 | 406 | if (ret == -1) { | 406 | 407 | PrintSystemError(errno); | 407 | 408 | } | | 409 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 408 | 410 | return -1; | 409 | 411 | } | | 412 | + if (-1 == munmap(nmem, size)) PrintSystemError(errno); | 410 | 413 | return ret; | 411 | 414 | } | 412 | 415 |
| @@ -418,12 +421,12 @@ int MapStaticCodeToLargePages() { | 418 | 421 | return -1; | 419 | 422 | } | 420 | 423 |
| 421 | | -#if defined(__linux__) | | 424 | +#if defined(__linux__) || defined(__FreeBSD__) | 422 | 425 | if (r.from > reinterpret_cast<void*>(&MoveTextRegionToLargePages)) | 423 | 426 | return MoveTextRegionToLargePages(r); | 424 | 427 |
| 425 | 428 | return -1; | 426 | | -#elif defined(__FreeBSD__) || defined(__APPLE__) | | 429 | +#elif defined(__APPLE__) | 427 | 430 | return MoveTextRegionToLargePages(r); | 428 | 431 | #endif | 429 | 432 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/node.cc +20-10Lines changed: 20 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 64 | 64 | #include "inspector/worker_inspector.h" // ParentInspectorHandle | 65 | 65 | #endif | 66 | 66 |
| 67 | | -#ifdef NODE_ENABLE_LARGE_CODE_PAGES | 68 | 67 | #include "large_pages/node_large_page.h" | 69 | | -#endif | 70 | 68 |
| 71 | 69 | #ifdef NODE_REPORT | 72 | 70 | #include "node_report.h" | @@ -887,14 +885,6 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { | 887 | 885 |
| 888 | 886 | CHECK_GT(argc, 0); | 889 | 887 |
| 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 | | - | 898 | 888 | // Hack around with the argv pointer. Used for process.title = "blah". | 899 | 889 | argv = uv_setup_args(argc, argv); | 900 | 890 |
| @@ -914,6 +904,26 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { | 914 | 904 | } | 915 | 905 | } | 916 | 906 |
| | 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 | + | 917 | 927 | if (per_process::cli_options->print_version) { | 918 | 928 | printf("%s\n", NODE_VERSION); | 919 | 929 | result.exit_code = 0; | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.cc +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -63,6 +63,11 @@ void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) { | 63 | 63 | "used, not both"); | 64 | 64 | } | 65 | 65 | #endif | | 66 | + if (use_largepages != "off" && | | 67 | + use_largepages != "on" && | | 68 | + use_largepages != "silent") { | | 69 | + errors->push_back("invalid value for --use-largepages"); | | 70 | + } | 66 | 71 | per_isolate->CheckOptions(errors); | 67 | 72 | } | 68 | 73 |
| @@ -745,6 +750,10 @@ PerProcessOptionsParser::PerProcessOptionsParser( | 745 | 750 | kAllowedInEnvironment); | 746 | 751 | #endif | 747 | 752 | #endif | | 753 | + AddOption("--use-largepages", | | 754 | + "Map the Node.js static code to large pages", | | 755 | + &PerProcessOptions::use_largepages, | | 756 | + kAllowedInEnvironment); | 748 | 757 |
| 749 | 758 | // v12.x backwards compat flags removed in V8 7.9. | 750 | 759 | AddOption("--fast_calls_with_arguments_mismatches", "", NoOp{}); | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -231,6 +231,7 @@ class PerProcessOptions : public Options { | 231 | 231 | bool force_fips_crypto = false; | 232 | 232 | #endif | 233 | 233 | #endif | | 234 | + std::string use_largepages = "off"; | 234 | 235 |
| 235 | 236 | #ifdef NODE_REPORT | 236 | 237 | std::vector<std::string> cmdline; | |
Collapse file Copy file name to clipboard +29Lines changed: 29 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 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. |
|