Commit ce66eec8 authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Introduce hard limit for external memory

We introduce, similar to regular heap, a hard and a soft limit for external memory.
- Upon reaching the hard limit we do a full GC. The hard limit is a a delta from
  the size of external memory at last GC.
- Upon reaching the soft limit we start incremental marking. Each further
  AdjustAmountOfExternalMemory will trigger a marking step. The step size depends
  on how far we are away from the hard limit. Further away means we have still
  some wiggle room and the step will be small. Being closer to the hard limit
  makes it more likely to trigger a full GC, so we increase the step size.

BUG=chromium:621829

Review-Url: https://codereview.chromium.org/2256853003
Cr-Commit-Position: refs/heads/master@{#39133}
parent 883e0e70
......@@ -916,11 +916,6 @@ DEFINE_BOOL(manual_evacuation_candidates_selection, false,
"Test mode only flag. It allows an unit test to select evacuation "
"candidates pages (requires --stress_compaction).")
// api.cc
DEFINE_INT(external_allocation_limit_incremental_time, 1,
"Time spent in incremental marking steps (in ms) once the external "
"allocation limit is reached")
DEFINE_BOOL(disable_old_api_accessors, false,
"Disable old-style API accessors whose setters trigger through the "
"prototype chain")
......
......@@ -193,9 +193,8 @@ const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
const size_t kReservedCodeRangePages = 0;
#endif
// The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory.
const int kExternalAllocationLimit = 192 * 1024 * 1024;
// Trigger an incremental GCs once the external memory reaches this limit.
const int kExternalAllocationSoftLimit = 64 * MB;
STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
......
......@@ -71,7 +71,7 @@ class IdleScavengeObserver : public AllocationObserver {
Heap::Heap()
: external_memory_(0),
external_memory_limit_(kExternalAllocationLimit),
external_memory_limit_(kExternalAllocationSoftLimit),
external_memory_at_last_mark_compact_(0),
isolate_(nullptr),
code_range_size_(0),
......@@ -903,6 +903,14 @@ void Heap::CollectAllAvailableGarbage(const char* gc_reason) {
void Heap::ReportExternalMemoryPressure(const char* gc_reason) {
if (external_memory_ >
(external_memory_at_last_mark_compact_ + external_memory_hard_limit())) {
CollectAllGarbage(
kReduceMemoryFootprintMask | kFinalizeIncrementalMarkingMask, gc_reason,
static_cast<GCCallbackFlags>(kGCCallbackFlagCollectAllAvailableGarbage |
kGCCallbackFlagCollectAllExternalMemory));
return;
}
if (incremental_marking()->IsStopped()) {
if (incremental_marking()->CanBeActivated()) {
StartIncrementalMarking(
......@@ -917,11 +925,15 @@ void Heap::ReportExternalMemoryPressure(const char* gc_reason) {
}
} else {
// Incremental marking is turned on an has already been started.
// TODO(mlippautz): Compute the time slice for incremental marking based on
// memory pressure.
double deadline = MonotonicallyIncreasingTimeInMs() +
FLAG_external_allocation_limit_incremental_time;
const double pressure =
static_cast<double>(external_memory_ -
external_memory_at_last_mark_compact_ -
kExternalAllocationSoftLimit) /
external_memory_hard_limit();
DCHECK_GE(1, pressure);
const double kMaxStepSizeOnExternalLimit = 25;
const double deadline = MonotonicallyIncreasingTimeInMs() +
pressure * kMaxStepSizeOnExternalLimit;
incremental_marking()->AdvanceIncrementalMarking(
deadline,
IncrementalMarking::StepActions(IncrementalMarking::GC_VIA_STACK_GUARD,
......@@ -1362,7 +1374,7 @@ bool Heap::PerformGarbageCollection(
if (collector == MARK_COMPACTOR) {
// Register the amount of external allocated memory.
external_memory_at_last_mark_compact_ = external_memory_;
external_memory_limit_ = external_memory_ + kExternalAllocationLimit;
external_memory_limit_ = external_memory_ + kExternalAllocationSoftLimit;
SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed);
} else if (HasLowYoungGenerationAllocationRate() &&
old_generation_size_configured_) {
......
......@@ -841,6 +841,8 @@ class Heap {
global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax;
}
int64_t external_memory_hard_limit() { return MaxOldGenerationSize() / 2; }
int64_t external_memory() { return external_memory_; }
void update_external_memory(int64_t delta) { external_memory_ += delta; }
......
......@@ -14899,7 +14899,8 @@ THREADED_TEST(ExternalAllocatedMemory) {
isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
CHECK_EQ(baseline,
isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
const int64_t kTriggerGCSize =
CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
CHECK_EQ(baseline + kTriggerGCSize,
isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
CHECK_EQ(baseline,
......@@ -14911,7 +14912,8 @@ TEST(Regress51719) {
i::FLAG_incremental_marking = false;
CcTest::InitializeVM();
const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
const int64_t kTriggerGCSize =
CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
v8::Isolate* isolate = CcTest::isolate();
isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment