Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0a76c7e
Initial Large Page (2M) support for node.js
suresh-srinivas Mar 23, 2018
fa0e324
Add support for checking if explicitHugePages and transparentHugePage…
suresh-srinivas Mar 26, 2018
fdb45cd
Added License headers
suresh-srinivas Mar 30, 2018
b7791c2
Get rid of waring messages & code cleanup
suresh-srinivas Mar 30, 2018
6631eea
Protect the large pages under #ifdef NODE_ENABLE_LARGE_CODE_PAGES and…
suresh-srinivas Apr 4, 2018
843089c
Added configure option to enable huge pages
uttampawar Apr 9, 2018
077bc01
Added else clause to set node_use_large_pages=false by default
uttampawar Apr 9, 2018
7bdd9fc
Merge branch 'configure_fixes' into 2M-Pages-For-Code-16198
uttampawar Apr 9, 2018
b91de5a
Finished adding checks at appropriate places to handle possible error…
uttampawar May 8, 2018
7ef956a
Changed return type for two function from void to int
uttampawar May 9, 2018
b02e7a9
Fixed lint errors.
uttampawar May 24, 2018
2af82b1
Added one more condition check for verify the start address of newly …
uttampawar May 26, 2018
cae9285
Fixed syntax error due to wring data type. int64 to int64_t
uttampawar May 30, 2018
30114b6
Removed explictHugePages code
suresh-srinivas May 30, 2018
39e1f0d
Merge branch 'add-checks' into 2M-Pages-For-Code-16198
suresh-srinivas May 30, 2018
49cd0de
Merge branch '2M-Pages-For-Code-16198' of https://github.intel.com/DS…
suresh-srinivas May 30, 2018
2dd9e8c
Added Large Page Support
suresh-srinivas May 30, 2018
51d0f02
Merge branch 'intel-large-pages' of https://github.com/suresh-sriniva…
suresh-srinivas May 31, 2018
2f672ee
Update PR based on feedback
suresh-srinivas Jun 1, 2018
31504cc
Addressing the additional PR feedback
suresh-srinivas Jun 3, 2018
f998c58
Fix the gypi style issue
suresh-srinivas Jun 3, 2018
9f15cfc
Update with stylistic changes (eg char* instead of char *, IsLargePag…
suresh-srinivas Jun 4, 2018
d6de361
Add additional guard so large pages is only under Linux and target_ar…
suresh-srinivas Jun 4, 2018
29c7d13
Style fixes according to the Node C++ Style Guide
suresh-srinivas Jun 4, 2018
9828036
Eliminate ld.script and use implicit script
suresh-srinivas Jun 7, 2018
600cf54
Add #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
suresh-srinivas Jun 7, 2018
bf259e2
Fix the test failures
suresh-srinivas Jun 7, 2018
f0a6dcb
Add detailed help message to configure --with-largepages
suresh-srinivas Jun 8, 2018
4610793
Fix style issues and created inline functions instead of macros for a…
suresh-srinivas Jun 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed lint errors.
  • Loading branch information
uttampawar committed May 24, 2018
commit b02e7a982f0b37b245797c8ffee5aa14eb37f2d5
8 changes: 4 additions & 4 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4424,7 +4424,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,

return exit_code;
}

inline int Start(uv_loop_t* event_loop,
int argc, const char* const* argv,
int exec_argc, const char* const* exec_argv) {
Expand All @@ -4435,7 +4435,7 @@ inline int Start(uv_loop_t* event_loop,
params.code_event_handler = vTune::GetVtuneCodeEventHandler();
#endif


Isolate* const isolate = Isolate::New(params);
if (isolate == nullptr)
return 12; // Signal internal error.
Expand Down Expand Up @@ -4487,8 +4487,8 @@ int Start(int argc, char** argv) {

#ifdef NODE_ENABLE_LARGE_CODE_PAGES
if (node::largepages::isLargePagesEnabled()) {
if ( (node::largepages::map_static_code_to_large_pages()) != 0) {
fprintf(stderr, "Warning: Mapping of static code to large pages failed.\n");
if ((node::largepages::map_static_code_to_large_pages()) != 0) {
fprintf(stderr, "Mapping of static code to large pages failed.\n");
}
}
#endif
Expand Down
60 changes: 30 additions & 30 deletions src/node_large_page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,18 @@ extern char __etext;
extern char __nodetext;

namespace node {
namespace largepages {
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define PAGE_ALIGN_UP(x,a) ALIGN(x,a)
#define PAGE_ALIGN_DOWN(x,a) ((x) & ~((a) - 1))

struct TextRegion {
void * from;
void * to;
int totalHugePages;
long offset;
bool found_text_region;
char name[PATH_MAX];
};
namespace largepages {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not sure this qualifies for a separate namespace.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure. I wanted the structure and code to live in a separate space and not pollute the node space.

#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define PAGE_ALIGN_UP(x, a) ALIGN(x, a)
#define PAGE_ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

style nit: these could all be inline functions, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Yes fixed them to be inline functions.


struct TextRegion {
void * from;
void * to;
int totalHugePages;
int64 offset;
bool found_text_region;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how many of these fields are used?
can we follow a consistent variable naming convention? (camel casing vs snake casing etc.) I suggest look around in node.cc for the prevailing nomenclature.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, will look and make it consistent.

static void printSystemError(int error) {
fprintf(stderr, "Hugepages WARNING: %s\n", strerror(error));
Expand All @@ -67,7 +66,7 @@ namespace node {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am against printing anything - if this whole exercise works or fails, let it be transparent to outside.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is easy to trip up on some OS configuration/settings. At the beginning as this is getting tested on more systems, we wanted to be able to provide some messages for users so we can also fix those problems.

static struct TextRegion find_node_text_region() {
FILE *f;
long unsigned int start, end, offset, inode;
unsigned int64 start, end, offset, inode;
char perm[5], dev[6], name[256];
int ret;
const size_t hugePageSize = 2L * 1024 * 1024;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

does it have a bearing to existing Linux attributes? Are they same across releases and vendors? are they tunable at OS level?

Copy link
Copy Markdown
Contributor Author

@suresh-srinivas suresh-srinivas Jun 1, 2018

Choose a reason for hiding this comment

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

The structure of /proc//maps is consistent across many different releases/vendors.

man proc
/proc/[pid]/maps
A file containing the currently mapped memory regions and their access permissions.

          The format of the file is:
   address           perms offset  dev   inode       pathname
   00400000-00452000 r-xp 00000000 08:02 173521      /usr/bin/dbus-daemon
   00651000-00652000 r--p 00051000 08:02 173521      /usr/bin/dbus-daemon
   00652000-00655000 rw-p 00052000 08:02 173521      /usr/bin/dbus-daemon
   00e03000-00e24000 rw-p 00000000 00:00 0           [heap]
   00e24000-011f7000 rw-p 00000000 00:00 0           [heap]
   ...
   35b1800000-35b1820000 r-xp 00000000 08:02 135522  /usr/lib64/ld-2.15.so
   35b1a1f000-35b1a20000 r--p 0001f000 08:02 135522  /usr/lib64/ld-2.15.so
   35b1a20000-35b1a21000 rw-p 00020000 08:02 135522  /usr/lib64/ld-2.15.so
   35b1a21000-35b1a22000 rw-p 00000000 00:00 0

For the node process it looks like this.

00400000-02168000 r-xp 00000000 08:01 541586     /home/dslo/node-ssuresh-fork/node
02367000-02369000 r--p 01d67000 08:01 541586      /home/dslo/node-ssuresh-fork/node
02369000-02380000 rw-p 01d69000 08:01 541586     /home/dslo/node-ssuresh-fork/node
02380000-0248f000 rw-p 00000000 00:00 0                                  [heap]

After we map part of the area, you will see the text spilt into 3 executable pages. I will put this in the code comment as well.

00400000-00a00000 r-xp 00000000 08:01 541593    /home/dslo/node-ssuresh-fork/node.large
00a00000-02200000 r-xp 00000000 00:00 0 
02200000-02397000 r-xp 01e00000 08:01 541593    /home/dslo/node-ssuresh-fork/node.large
02597000-02598000 r--p 01f97000 08:01 541593     /home/dslo/node-ssuresh-fork/node.large
02598000-025af000 rw-p 01f98000 08:01 541593     /home/dslo/node-ssuresh-fork/node.large
025af000-025c7000 rw-p 00000000 00:00 0 
036df000-037d2000 rw-p 00000000 00:00 0                                  [heap]

Expand All @@ -82,11 +81,10 @@ namespace node {

if (ret == 7 &&
perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x') {

// Checking if the region is from node binary and executable
start = (unsigned int long) &__nodetext;
char *from = (char *)PAGE_ALIGN_UP(start, hugePageSize);
char *to = (char *)PAGE_ALIGN_DOWN(end, hugePageSize);
start = (unsigned int64) &__nodetext;
char *from = reinterpret_cast<char *>PAGE_ALIGN_UP(start, hugePageSize);
char *to = reinterpret_cast<char *>PAGE_ALIGN_DOWN(end, hugePageSize);

if (from < to) {
size_t size = (intptr_t)to - (intptr_t)from;
Expand All @@ -95,7 +93,6 @@ namespace node {
nregion.to = to;
nregion.offset = offset;
nregion.totalHugePages = size/hugePageSize;
strcpy(nregion.name,name);
return nregion;
}
}
Expand All @@ -108,13 +105,13 @@ namespace node {

ifs.open("/sys/kernel/mm/transparent_hugepage/enabled");
if (!ifs) {
fprintf(stderr, "Hugepages WARNING: Couldn't check hugepages support\n");
fprintf(stderr, "WARNING: Couldn't check hugepages support\n");
return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can we follow a consistent return value convention? (returning null vs. -1 vs errno) I suggest look arounf in other APIs for the prevailing convention.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure

}

std::string always, madvise, never;
if (ifs.is_open()) {
while(ifs >> always >> madvise >> never) ;
while (ifs >> always >> madvise >> never) {}
}

int ret_status = false;
Expand All @@ -123,6 +120,8 @@ namespace node {
ret_status = true;
else if (madvise.compare("[madvise]") == 0)
ret_status = true;
else if (never.compare("[never]") == 0)
ret_status = false;

ifs.close();
return ret_status;
Expand All @@ -132,9 +131,9 @@ namespace node {
int ret_status = false;
std::string kw;
std::ifstream file("/proc/meminfo");
while(file >> kw) {
if(kw == "HugePages_Total:") {
unsigned long hp_tot;
while (file >> kw) {
if (kw == "HugePages_Total:") {
unsigned int64 hp_tot;
file >> hp_tot;
if (hp_tot > 0)
ret_status = true;
Expand Down Expand Up @@ -162,14 +161,14 @@ namespace node {
__attribute__((__noinline__))
__attribute__((__optimize__("2")))
move_text_region_to_large_pages(struct TextRegion r) {
void *nmem = NULL, *tmem = NULL;
int ret=0;
void *nmem = nullptr, *tmem = nullptr;
int ret = 0;

size_t size = (intptr_t)r.to - (intptr_t)r.from;
void *start = r.from;

// Allocate temporary region preparing for copy
nmem = mmap(NULL, size,
nmem = mmap(nullptr, size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (nmem == MAP_FAILED) {
printSystemError(errno);
Expand Down Expand Up @@ -237,7 +236,7 @@ namespace node {
return -1;
}

if (n.to <= (void *) & move_text_region_to_large_pages)
if (n.to <= reinterpret_cast<void *> & move_text_region_to_large_pages)
return move_text_region_to_large_pages(n);

return -1;
Expand All @@ -246,5 +245,6 @@ namespace node {
bool isLargePagesEnabled() {
return isExplicitHugePagesEnabled() || isTransparentHugePagesEnabled();
}
}
}

} // namespace largepages
} // namespace node
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I admit I kinda checked out after the first 100 lines. This file has so many style errors, can you fix those first, please?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Could you be specific? I ran the make -s lint and fixed all the ones pointed to by that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The linter doesn't catch everything but to name three things:

  1. Inconsistent indentation.
  2. Star leans left in pointers (void* p, not void *p or void * p.)
  3. Casing: IsLargePagesEnabled, not isLargePagesEnabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks I have updated the PR with 2) and 3). I am using standard indentation of 2 spaces.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@suresh-srinivas There’s https://github.com/nodejs/node/blob/master/CPP_STYLE_GUIDE.md that would help a lot with this. Also, comparing with other code in our codebase if you’re unsure. :)

(In particular, we don’t indent code inside namespaces)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@addaleax thanks much. I will look at this and fix styles accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@addaleax @bnoordhuis @gireeshpunathil fixed the style errors. Let me know if you see anything else.

62 changes: 30 additions & 32 deletions src/node_large_page.h
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
/*
Copyright (C) 2018 Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.

SPDX-License-Identifier: MIT
*/

#ifndef NODE_LARGEPAGE_H_
#define NODE_LARGEPAGE_H_
// Copyright (C) 2018 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
//
// SPDX-License-Identifier: MIT

#ifndef SRC_NODE_LARGE_PAGE_H_
#define SRC_NODE_LARGE_PAGE_H_

namespace node {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be enclosed in

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks I fixed it.

namespace largepages {
bool isLargePagesEnabled();
int map_static_code_to_large_pages();
} // namespace largepages
} // namespace node
namespace largepages {
bool isLargePagesEnabled();
int map_static_code_to_large_pages();
} // namespace largepages
} // namespace node

#endif // NODE_LARGE_PAGE_H_
#endif // SRC_NODE_LARGE_PAGE_H_