Commit b238864d authored by ulan's avatar ulan Committed by Commit bot

Activate memory reducer for small heaps in background tabs.

BUG=chromium:587574
LOG=NO

Review URL: https://codereview.chromium.org/1705183003

Cr-Commit-Position: refs/heads/master@{#34188}
parent 0e43ff56
......@@ -1063,9 +1063,9 @@ int Heap::NotifyContextDisposed(bool dependant_context) {
tracer()->ResetSurvivalEvents();
old_generation_size_configured_ = false;
MemoryReducer::Event event;
event.type = MemoryReducer::kContextDisposed;
event.type = MemoryReducer::kPossibleGarbage;
event.time_ms = MonotonicallyIncreasingTimeInMs();
memory_reducer_->NotifyContextDisposed(event);
memory_reducer_->NotifyPossibleGarbage(event);
}
if (isolate()->concurrent_recompilation_enabled()) {
// Flush the queued recompilation tasks.
......@@ -4113,6 +4113,20 @@ bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) {
return committed - used > used + kSlack;
}
void Heap::SetOptimizeForMemoryUsage() {
// Activate memory reducer when switching to background if
// - there was no mark compact since the start.
// - the committed memory can be potentially reduced.
// 2 pages for the old, code, and map space + 1 page for new space.
const int kMinCommittedMemory = 7 * Page::kPageSize;
if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory) {
MemoryReducer::Event event;
event.type = MemoryReducer::kPossibleGarbage;
event.time_ms = MonotonicallyIncreasingTimeInMs();
memory_reducer_->NotifyPossibleGarbage(event);
}
optimize_for_memory_usage_ = true;
}
void Heap::ReduceNewSpaceSize() {
// TODO(ulan): Unify this constant with the similar constant in
......
......@@ -821,7 +821,7 @@ class Heap {
bool HasHighFragmentation(intptr_t used, intptr_t committed);
void SetOptimizeForLatency() { optimize_for_memory_usage_ = false; }
void SetOptimizeForMemoryUsage() { optimize_for_memory_usage_ = true; }
void SetOptimizeForMemoryUsage();
bool ShouldOptimizeForMemoryUsage() { return optimize_for_memory_usage_; }
// ===========================================================================
......
......@@ -444,7 +444,16 @@ void IncrementalMarking::ActivateIncrementalWriteBarrier() {
bool IncrementalMarking::ShouldActivateEvenWithoutIdleNotification() {
#ifndef DEBUG
static const intptr_t kActivationThreshold = 8 * MB;
#else
// TODO(gc) consider setting this to some low level so that some
// debug tests run with incremental marking and some without.
static const intptr_t kActivationThreshold = 0;
#endif
// Don't switch on for very small heaps.
return CanBeActivated() &&
heap_->PromotedSpaceSizeOfObjects() > kActivationThreshold &&
heap_->HeapIsFullEnoughToStartIncrementalMarking(
heap_->old_generation_allocation_limit());
}
......@@ -454,21 +463,12 @@ bool IncrementalMarking::WasActivated() { return was_activated_; }
bool IncrementalMarking::CanBeActivated() {
#ifndef DEBUG
static const intptr_t kActivationThreshold = 8 * MB;
#else
// TODO(gc) consider setting this to some low level so that some
// debug tests run with incremental marking and some without.
static const intptr_t kActivationThreshold = 0;
#endif
// Only start incremental marking in a safe state: 1) when incremental
// marking is turned on, 2) when we are currently not in a GC, and
// 3) when we are currently not serializing or deserializing the heap.
// Don't switch on for very small heaps.
return FLAG_incremental_marking && heap_->gc_state() == Heap::NOT_IN_GC &&
heap_->deserialization_complete() &&
!heap_->isolate()->serializer_enabled() &&
heap_->PromotedSpaceSizeOfObjects() > kActivationThreshold;
!heap_->isolate()->serializer_enabled();
}
......
......@@ -47,7 +47,7 @@ void MemoryReducer::TimerTask::RunInternal() {
event.should_start_incremental_gc = is_idle || optimize_for_memory;
event.can_start_incremental_gc =
heap->incremental_marking()->IsStopped() &&
heap->incremental_marking()->CanBeActivated();
(heap->incremental_marking()->CanBeActivated() || optimize_for_memory);
memory_reducer_->NotifyTimer(event);
}
......@@ -118,9 +118,8 @@ void MemoryReducer::NotifyMarkCompact(const Event& event) {
}
}
void MemoryReducer::NotifyContextDisposed(const Event& event) {
DCHECK_EQ(kContextDisposed, event.type);
void MemoryReducer::NotifyPossibleGarbage(const Event& event) {
DCHECK_EQ(kPossibleGarbage, event.type);
Action old_action = state_.action;
state_ = Step(state_, event);
if (old_action != kWait && state_.action == kWait) {
......@@ -147,14 +146,14 @@ MemoryReducer::State MemoryReducer::Step(const State& state,
if (event.type == kTimer) {
return state;
} else {
DCHECK(event.type == kContextDisposed || event.type == kMarkCompact);
DCHECK(event.type == kPossibleGarbage || event.type == kMarkCompact);
return State(
kWait, 0, event.time_ms + kLongDelayMs,
event.type == kMarkCompact ? event.time_ms : state.last_gc_time_ms);
}
case kWait:
switch (event.type) {
case kContextDisposed:
case kPossibleGarbage:
return state;
case kTimer:
if (state.started_gcs >= kMaxNumberOfGCs) {
......
......@@ -96,7 +96,7 @@ class MemoryReducer {
double last_gc_time_ms;
};
enum EventType { kTimer, kMarkCompact, kContextDisposed };
enum EventType { kTimer, kMarkCompact, kPossibleGarbage };
struct Event {
EventType type;
......@@ -113,7 +113,7 @@ class MemoryReducer {
js_calls_sample_time_ms_(0.0) {}
// Callbacks.
void NotifyMarkCompact(const Event& event);
void NotifyContextDisposed(const Event& event);
void NotifyPossibleGarbage(const Event& event);
void NotifyBackgroundIdleNotification(const Event& event);
// The step function that computes the next state from the current state and
// the incoming event.
......
......@@ -74,10 +74,9 @@ MemoryReducer::Event TimerEventPendingGC(double time_ms) {
return TimerEvent(time_ms, true, false);
}
MemoryReducer::Event ContextDisposedEvent(double time_ms) {
MemoryReducer::Event PossibleGarbageEvent(double time_ms) {
MemoryReducer::Event event;
event.type = MemoryReducer::kContextDisposed;
event.type = MemoryReducer::kPossibleGarbage;
event.time_ms = time_ms;
return event;
}
......@@ -114,7 +113,7 @@ TEST(MemoryReducer, FromDoneToWait) {
EXPECT_EQ(0, state1.started_gcs);
EXPECT_EQ(2, state1.last_gc_time_ms);
state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0));
state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(0));
EXPECT_EQ(MemoryReducer::kWait, state1.action);
EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
EXPECT_EQ(0, state1.started_gcs);
......@@ -127,7 +126,7 @@ TEST(MemoryReducer, FromWaitToWait) {
MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState());
state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
EXPECT_EQ(MemoryReducer::kWait, state1.action);
EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
......@@ -250,7 +249,7 @@ TEST(MemoryReducer, FromRunToRun) {
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
EXPECT_EQ(MemoryReducer::kRun, state1.action);
EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
......
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