mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
src: initial enablement of IsolateGroups
This lays the initial groundwork for enabling the use of IsolateGroups. Every isolate in V8 is created within a group. When pointer compression is enabled, all isolates within a single group are limited to a 4 GB shared pointer cage. By default, all isolates in the process share the same group, which means that when running with pointer compression, the entire process would be limited to a single 4 GB shared pointer cage. But, we can create as many IsolateGroups as we want, limited only by the amount of virtual memory available on the machine. PR-URL: https://github.com/nodejs/node/pull/60254 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
e6d94ef106
commit
c2f3c2131d
|
|
@ -443,6 +443,9 @@
|
||||||
['v8_enable_pointer_compression == 1', {
|
['v8_enable_pointer_compression == 1', {
|
||||||
'defines': ['V8_COMPRESS_POINTERS'],
|
'defines': ['V8_COMPRESS_POINTERS'],
|
||||||
}],
|
}],
|
||||||
|
['v8_enable_pointer_compression == 1 and v8_enable_pointer_compression_shared_cage != 1', {
|
||||||
|
'defines': ['V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES'],
|
||||||
|
}],
|
||||||
['v8_enable_pointer_compression_shared_cage == 1', {
|
['v8_enable_pointer_compression_shared_cage == 1', {
|
||||||
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
|
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
11
configure.py
11
configure.py
|
|
@ -646,6 +646,12 @@ parser.add_argument('--experimental-enable-pointer-compression',
|
||||||
default=None,
|
default=None,
|
||||||
help='[Experimental] Enable V8 pointer compression (limits max heap to 4GB and breaks ABI compatibility)')
|
help='[Experimental] Enable V8 pointer compression (limits max heap to 4GB and breaks ABI compatibility)')
|
||||||
|
|
||||||
|
parser.add_argument('--experimental-pointer-compression-shared-cage',
|
||||||
|
action='store_true',
|
||||||
|
dest='pointer_compression_shared_cage',
|
||||||
|
default=None,
|
||||||
|
help='[Experimental] Use V8 pointer compression with shared cage (requires --experimental-enable-pointer-compression)')
|
||||||
|
|
||||||
parser.add_argument('--v8-options',
|
parser.add_argument('--v8-options',
|
||||||
action='store',
|
action='store',
|
||||||
dest='v8_options',
|
dest='v8_options',
|
||||||
|
|
@ -1789,7 +1795,10 @@ def configure_v8(o, configs):
|
||||||
# Note that enabling pointer compression without enabling sandbox is unsupported by V8,
|
# Note that enabling pointer compression without enabling sandbox is unsupported by V8,
|
||||||
# so this can be broken at any time.
|
# so this can be broken at any time.
|
||||||
o['variables']['v8_enable_sandbox'] = 0
|
o['variables']['v8_enable_sandbox'] = 0
|
||||||
o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.enable_pointer_compression else 0
|
# We set v8_enable_pointer_compression_shared_cage to 0 always, even when
|
||||||
|
# pointer compression is enabled so that we don't accidentally enable shared
|
||||||
|
# cage mode when pointer compression is on.
|
||||||
|
o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.pointer_compression_shared_cage else 0
|
||||||
o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0
|
o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0
|
||||||
o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0
|
o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0
|
||||||
o['variables']['v8_enable_extensible_ro_snapshot'] = 0
|
o['variables']['v8_enable_extensible_ro_snapshot'] = 0
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "debug_utils-inl.h"
|
#include "debug_utils-inl.h"
|
||||||
#include "env-inl.h"
|
#include "env-inl.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "node_internals.h"
|
||||||
#include "node_snapshot_builder.h"
|
#include "node_snapshot_builder.h"
|
||||||
|
|
||||||
using v8::Context;
|
using v8::Context;
|
||||||
|
|
@ -127,7 +128,7 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
|
||||||
if (flags & Flags::kIsForSnapshotting) {
|
if (flags & Flags::kIsForSnapshotting) {
|
||||||
// The isolate must be registered before the SnapshotCreator initializes the
|
// The isolate must be registered before the SnapshotCreator initializes the
|
||||||
// isolate, so that the memory reducer can be initialized.
|
// isolate, so that the memory reducer can be initialized.
|
||||||
isolate = impl_->isolate = Isolate::Allocate();
|
isolate = impl_->isolate = Isolate::Allocate(GetOrCreateIsolateGroup());
|
||||||
platform->RegisterIsolate(isolate, loop);
|
platform->RegisterIsolate(isolate, loop);
|
||||||
|
|
||||||
impl_->snapshot_creator.emplace(isolate, params);
|
impl_->snapshot_creator.emplace(isolate, params);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ using v8::Function;
|
||||||
using v8::FunctionCallbackInfo;
|
using v8::FunctionCallbackInfo;
|
||||||
using v8::HandleScope;
|
using v8::HandleScope;
|
||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
|
using v8::IsolateGroup;
|
||||||
using v8::Just;
|
using v8::Just;
|
||||||
using v8::JustVoid;
|
using v8::JustVoid;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
|
|
@ -304,6 +305,17 @@ void SetIsolateUpForNode(v8::Isolate* isolate) {
|
||||||
SetIsolateUpForNode(isolate, settings);
|
SetIsolateUpForNode(isolate, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
IsolateGroup GetOrCreateIsolateGroup() {
|
||||||
|
// When pointer compression is disabled, we cannot create new groups,
|
||||||
|
// in which case we'll always return the default.
|
||||||
|
if (IsolateGroup::CanCreateNewGroups()) {
|
||||||
|
return IsolateGroup::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsolateGroup::GetDefault();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(joyeecheung): we may want to expose this, but then we need to be
|
// TODO(joyeecheung): we may want to expose this, but then we need to be
|
||||||
// careful about what we override in the params.
|
// careful about what we override in the params.
|
||||||
Isolate* NewIsolate(Isolate::CreateParams* params,
|
Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||||
|
|
@ -311,7 +323,8 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||||
MultiIsolatePlatform* platform,
|
MultiIsolatePlatform* platform,
|
||||||
const SnapshotData* snapshot_data,
|
const SnapshotData* snapshot_data,
|
||||||
const IsolateSettings& settings) {
|
const IsolateSettings& settings) {
|
||||||
Isolate* isolate = Isolate::Allocate();
|
IsolateGroup group = GetOrCreateIsolateGroup();
|
||||||
|
Isolate* isolate = Isolate::Allocate(group);
|
||||||
if (isolate == nullptr) return nullptr;
|
if (isolate == nullptr) return nullptr;
|
||||||
|
|
||||||
if (snapshot_data != nullptr) {
|
if (snapshot_data != nullptr) {
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@ extern uint64_t node_start_time;
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
class Environment;
|
class Environment;
|
||||||
|
|
||||||
|
static constexpr uint64_t kMaxPointerCompressionHeap = uint64_t{1}
|
||||||
|
<< 32; // 4 GiB
|
||||||
|
|
||||||
// Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object.
|
// Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object.
|
||||||
// Sets address and port properties on the info object and returns it.
|
// Sets address and port properties on the info object and returns it.
|
||||||
// If |info| is omitted, a new object is returned.
|
// If |info| is omitted, a new object is returned.
|
||||||
|
|
@ -342,6 +345,20 @@ void TraceEnvVar(Environment* env,
|
||||||
v8::Local<v8::String> key);
|
v8::Local<v8::String> key);
|
||||||
|
|
||||||
void DefineZlibConstants(v8::Local<v8::Object> target);
|
void DefineZlibConstants(v8::Local<v8::Object> target);
|
||||||
|
|
||||||
|
// If creating new v8::IsolateGroup instance is supported, this returns a
|
||||||
|
// new instance. Otherwise, it returns the default instance.
|
||||||
|
//
|
||||||
|
// An IsolateGroup is a collection of Isolates that share the same underlying
|
||||||
|
// pointer cage when pointer compression is enabled. When pointer compression is
|
||||||
|
// disabled, there is a default IsolateGroup that is used for all isolates, and
|
||||||
|
// when pointer compression is enabled, all isolates in the app share the
|
||||||
|
// same pointer cage by default that is limited a maximum of 4GB, not counting
|
||||||
|
// array buffers and off-heap storage. Multiple IsolateGroups can be used to
|
||||||
|
// work around the 4GB limit, but each group reserves a range of virtual memory
|
||||||
|
// addresses, so this should be used with care.
|
||||||
|
v8::IsolateGroup GetOrCreateIsolateGroup();
|
||||||
|
|
||||||
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
|
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
|
||||||
uv_loop_t* event_loop,
|
uv_loop_t* event_loop,
|
||||||
MultiIsolatePlatform* platform,
|
MultiIsolatePlatform* platform,
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,15 @@ void PerIsolateOptions::HandleMaxOldSpaceSizePercentage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get available memory in bytes
|
// Get available memory in bytes
|
||||||
|
#ifdef V8_COMPRESS_POINTERS
|
||||||
|
// When pointer compression is enabled, V8 uses a 4 GiB heap limit.
|
||||||
|
// We'll use the smaller of that or the total system memory as
|
||||||
|
// reported by uv.
|
||||||
|
uint64_t total_memory =
|
||||||
|
std::min(uv_get_total_memory(), kMaxPointerCompressionHeap); // 4 GiB
|
||||||
|
#else
|
||||||
uint64_t total_memory = uv_get_total_memory();
|
uint64_t total_memory = uv_get_total_memory();
|
||||||
|
#endif
|
||||||
uint64_t constrained_memory = uv_get_constrained_memory();
|
uint64_t constrained_memory = uv_get_constrained_memory();
|
||||||
|
|
||||||
// Use constrained memory if available, otherwise use total memory
|
// Use constrained memory if available, otherwise use total memory
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,11 @@ assert(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Validate heap sizes against system memory
|
// Validate heap sizes against system memory
|
||||||
const totalMemoryMB = Math.floor(os.totalmem() / 1024 / 1024);
|
// When pointer compression is enabled, the maximum total memory is 4 GB
|
||||||
|
const totalmem = Math.floor(os.totalmem() / 1024 / 1024);
|
||||||
|
const totalMemoryMB = process.config.variables.v8_enable_pointer_compression ?
|
||||||
|
Math.min(4096, totalmem) :
|
||||||
|
totalmem;
|
||||||
const uint64Max = 2 ** 64 - 1;
|
const uint64Max = 2 ** 64 - 1;
|
||||||
const constrainedMemory = process.constrainedMemory();
|
const constrainedMemory = process.constrainedMemory();
|
||||||
const constrainedMemoryMB = Math.floor(constrainedMemory / 1024 / 1024);
|
const constrainedMemoryMB = Math.floor(constrainedMemory / 1024 / 1024);
|
||||||
|
|
|
||||||
|
|
@ -355,6 +355,9 @@
|
||||||
['v8_enable_pointer_compression==1', {
|
['v8_enable_pointer_compression==1', {
|
||||||
'defines': ['V8_COMPRESS_POINTERS'],
|
'defines': ['V8_COMPRESS_POINTERS'],
|
||||||
}],
|
}],
|
||||||
|
['v8_enable_pointer_compression==1 and v8_enable_pointer_compression_shared_cage!=1', {
|
||||||
|
'defines': ['V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES'],
|
||||||
|
}],
|
||||||
['v8_enable_pointer_compression_shared_cage==1', {
|
['v8_enable_pointer_compression_shared_cage==1', {
|
||||||
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
|
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user