Unify memory optimization modes and flags.

This patch folds --optimize-for-size flag and check for low-memory device
into Heap::ShouldOptimizeForMemoryUsage() predicate.

It has the following side effects:
- the heap growing factor for low-memory devices is capped at 1.3 (old value was 2.0).
- the memory reducer will be more aggressive for low-memory devices.

BUG=chromium:634900

Review-Url: https://codereview.chromium.org/2218703004
Cr-Commit-Position: refs/heads/master@{#38406}
This commit is contained in:
ulan 2016-08-07 08:33:36 -07:00 committed by Commit bot
parent 422d14350d
commit 6cebf7d963
6 changed files with 47 additions and 21 deletions

View File

@ -7858,13 +7858,13 @@ int Isolate::ContextDisposedNotification(bool dependant_context) {
void Isolate::IsolateInForegroundNotification() { void Isolate::IsolateInForegroundNotification() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
return isolate->heap()->SetOptimizeForLatency(); return isolate->IsolateInForegroundNotification();
} }
void Isolate::IsolateInBackgroundNotification() { void Isolate::IsolateInBackgroundNotification() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
return isolate->heap()->SetOptimizeForMemoryUsage(); return isolate->IsolateInBackgroundNotification();
} }
void Isolate::MemoryPressureNotification(MemoryPressureLevel level) { void Isolate::MemoryPressureNotification(MemoryPressureLevel level) {

View File

@ -112,7 +112,6 @@ Heap::Heap()
#endif // DEBUG #endif // DEBUG
old_generation_allocation_limit_(initial_old_generation_size_), old_generation_allocation_limit_(initial_old_generation_size_),
old_gen_exhausted_(false), old_gen_exhausted_(false),
optimize_for_memory_usage_(false),
inline_allocation_disabled_(false), inline_allocation_disabled_(false),
total_regexp_code_generated_(0), total_regexp_code_generated_(0),
tracer_(nullptr), tracer_(nullptr),
@ -4109,19 +4108,24 @@ bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) {
return committed - used > used + kSlack; return committed - used > used + kSlack;
} }
void Heap::SetOptimizeForMemoryUsage() { bool Heap::ShouldOptimizeForMemoryUsage() {
return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() ||
HighMemoryPressure() || IsLowMemoryDevice();
}
void Heap::ActivateMemoryReducerIfNeeded() {
// Activate memory reducer when switching to background if // Activate memory reducer when switching to background if
// - there was no mark compact since the start. // - there was no mark compact since the start.
// - the committed memory can be potentially reduced. // - the committed memory can be potentially reduced.
// 2 pages for the old, code, and map space + 1 page for new space. // 2 pages for the old, code, and map space + 1 page for new space.
const int kMinCommittedMemory = 7 * Page::kPageSize; const int kMinCommittedMemory = 7 * Page::kPageSize;
if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory) { if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory &&
isolate()->IsIsolateInBackground()) {
MemoryReducer::Event event; MemoryReducer::Event event;
event.type = MemoryReducer::kPossibleGarbage; event.type = MemoryReducer::kPossibleGarbage;
event.time_ms = MonotonicallyIncreasingTimeInMs(); event.time_ms = MonotonicallyIncreasingTimeInMs();
memory_reducer_->NotifyPossibleGarbage(event); memory_reducer_->NotifyPossibleGarbage(event);
} }
optimize_for_memory_usage_ = true;
} }
void Heap::ReduceNewSpaceSize() { void Heap::ReduceNewSpaceSize() {
@ -5081,6 +5085,7 @@ const double Heap::kMinHeapGrowingFactor = 1.1;
const double Heap::kMaxHeapGrowingFactor = 4.0; const double Heap::kMaxHeapGrowingFactor = 4.0;
const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0; const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0;
const double Heap::kMaxHeapGrowingFactorIdle = 1.5; const double Heap::kMaxHeapGrowingFactorIdle = 1.5;
const double Heap::kConservativeHeapGrowingFactor = 1.3;
const double Heap::kTargetMutatorUtilization = 0.97; const double Heap::kTargetMutatorUtilization = 0.97;
@ -5156,8 +5161,6 @@ intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor,
void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size,
double gc_speed, double gc_speed,
double mutator_speed) { double mutator_speed) {
const double kConservativeHeapGrowingFactor = 1.3;
double factor = HeapGrowingFactor(gc_speed, mutator_speed); double factor = HeapGrowingFactor(gc_speed, mutator_speed);
if (FLAG_trace_gc_verbose) { if (FLAG_trace_gc_verbose) {
@ -5168,14 +5171,12 @@ void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size,
gc_speed, mutator_speed); gc_speed, mutator_speed);
} }
// We set the old generation growing factor to 2 to grow the heap slower on if (IsMemoryConstrainedDevice()) {
// memory-constrained devices.
if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice ||
FLAG_optimize_for_size) {
factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained); factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained);
} }
if (memory_reducer_->ShouldGrowHeapSlowly() || optimize_for_memory_usage_) { if (memory_reducer_->ShouldGrowHeapSlowly() ||
ShouldOptimizeForMemoryUsage()) {
factor = Min(factor, kConservativeHeapGrowingFactor); factor = Min(factor, kConservativeHeapGrowingFactor);
} }

View File

@ -563,6 +563,7 @@ class Heap {
static const double kMaxHeapGrowingFactor; static const double kMaxHeapGrowingFactor;
static const double kMaxHeapGrowingFactorMemoryConstrained; static const double kMaxHeapGrowingFactorMemoryConstrained;
static const double kMaxHeapGrowingFactorIdle; static const double kMaxHeapGrowingFactorIdle;
static const double kConservativeHeapGrowingFactor;
static const double kTargetMutatorUtilization; static const double kTargetMutatorUtilization;
static const int kNoGCFlags = 0; static const int kNoGCFlags = 0;
@ -888,11 +889,18 @@ class Heap {
bool HasHighFragmentation(); bool HasHighFragmentation();
bool HasHighFragmentation(intptr_t used, intptr_t committed); bool HasHighFragmentation(intptr_t used, intptr_t committed);
void SetOptimizeForLatency() { optimize_for_memory_usage_ = false; } void ActivateMemoryReducerIfNeeded();
void SetOptimizeForMemoryUsage();
bool ShouldOptimizeForMemoryUsage() { bool ShouldOptimizeForMemoryUsage();
return optimize_for_memory_usage_ || HighMemoryPressure();
bool IsLowMemoryDevice() {
return max_old_generation_size_ <= kMaxOldSpaceSizeLowMemoryDevice;
} }
bool IsMemoryConstrainedDevice() {
return max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice;
}
bool HighMemoryPressure() { bool HighMemoryPressure() {
return memory_pressure_level_.Value() != MemoryPressureLevel::kNone; return memory_pressure_level_.Value() != MemoryPressureLevel::kNone;
} }
@ -2119,10 +2127,6 @@ class Heap {
// last GC. // last GC.
bool old_gen_exhausted_; bool old_gen_exhausted_;
// Indicates that memory usage is more important than latency.
// TODO(ulan): Merge it with memory reducer once chromium:490559 is fixed.
bool optimize_for_memory_usage_;
// Indicates that inline bump-pointer allocation has been globally disabled // Indicates that inline bump-pointer allocation has been globally disabled
// for all spaces. This is used to disable allocations in generated code. // for all spaces. This is used to disable allocations in generated code.
bool inline_allocation_disabled_; bool inline_allocation_disabled_;

View File

@ -1998,6 +1998,7 @@ Isolate::Isolate(bool enable_serializer)
has_fatal_error_(false), has_fatal_error_(false),
initialized_from_snapshot_(false), initialized_from_snapshot_(false),
is_tail_call_elimination_enabled_(true), is_tail_call_elimination_enabled_(true),
is_isolate_in_background_(false),
cpu_profiler_(NULL), cpu_profiler_(NULL),
heap_profiler_(NULL), heap_profiler_(NULL),
code_event_dispatcher_(new CodeEventDispatcher()), code_event_dispatcher_(new CodeEventDispatcher()),
@ -3172,6 +3173,15 @@ void Isolate::SetRAILMode(RAILMode rail_mode) {
} }
} }
void Isolate::IsolateInBackgroundNotification() {
is_isolate_in_background_ = false;
heap()->ActivateMemoryReducerIfNeeded();
}
void Isolate::IsolateInForegroundNotification() {
is_isolate_in_background_ = true;
}
bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const { bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
StackGuard* stack_guard = isolate_->stack_guard(); StackGuard* stack_guard = isolate_->stack_guard();
#ifdef USE_SIMULATOR #ifdef USE_SIMULATOR

View File

@ -1162,6 +1162,12 @@ class Isolate {
void SetRAILMode(RAILMode rail_mode); void SetRAILMode(RAILMode rail_mode);
void IsolateInForegroundNotification();
void IsolateInBackgroundNotification();
bool IsIsolateInBackground() { return is_isolate_in_background_; }
protected: protected:
explicit Isolate(bool enable_serializer); explicit Isolate(bool enable_serializer);
bool IsArrayOrObjectPrototype(Object* object); bool IsArrayOrObjectPrototype(Object* object);
@ -1353,6 +1359,10 @@ class Isolate {
// True if ES2015 tail call elimination feature is enabled. // True if ES2015 tail call elimination feature is enabled.
bool is_tail_call_elimination_enabled_; bool is_tail_call_elimination_enabled_;
// True if the isolate is in background. This flag is used
// to prioritize between memory usage and latency.
bool is_isolate_in_background_;
// Time stamp at initialization. // Time stamp at initialization.
double time_millis_at_init_; double time_millis_at_init_;

View File

@ -25348,6 +25348,7 @@ class MemoryPressureThread : public v8::base::Thread {
}; };
TEST(MemoryPressure) { TEST(MemoryPressure) {
if (v8::internal::FLAG_optimize_for_size) return;
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
WeakCallCounter counter(1234); WeakCallCounter counter(1234);