Commit c96a2d3a authored by hpayer's avatar hpayer Committed by Commit bot

Use smaller heap growing factor in idle notification to start incremental...

Use smaller heap growing factor in idle notification to start incremental marking when there is idle time >16ms.

BUG=chromium:477323
LOG=y

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

Cr-Commit-Position: refs/heads/master@{#27897}
parent 8924a9e1
......@@ -119,9 +119,12 @@ class GCIdleTimeHandler {
static const int kIdleScavengeThreshold;
// This is the maximum scheduled idle time. Note that it can be more than
// 16 ms when there is currently no rendering going on.
// 16.66 ms when there is currently no rendering going on.
static const size_t kMaxScheduledIdleTime = 50;
// The maximum idle time when frames are rendered is 16.66ms.
static const size_t kMaxFrameRenderingIdleTime = 17;
// We conservatively assume that in the next kTimeUntilNextIdleEvent ms
// no idle notification happens.
static const size_t kTimeUntilNextIdleEvent = 100;
......
......@@ -1131,8 +1131,7 @@ bool Heap::PerformGarbageCollection(
// Temporarily set the limit for case when PostGarbageCollectionProcessing
// allocates and triggers GC. The real limit is set at after
// PostGarbageCollectionProcessing.
old_generation_allocation_limit_ =
OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0);
SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0);
old_gen_exhausted_ = false;
old_generation_size_configured_ = true;
} else {
......@@ -1166,8 +1165,8 @@ bool Heap::PerformGarbageCollection(
// Register the amount of external allocated memory.
amount_of_external_allocated_memory_at_last_global_gc_ =
amount_of_external_allocated_memory_;
old_generation_allocation_limit_ = OldGenerationAllocationLimit(
PromotedSpaceSizeOfObjects(), freed_global_handles);
SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(),
freed_global_handles);
// We finished a marking cycle. We can uncommit the marking deque until
// we start marking again.
mark_compact_collector_.UncommitMarkingDeque();
......@@ -4548,7 +4547,7 @@ bool Heap::TryFinalizeIdleIncrementalMarking(
bool Heap::WorthActivatingIncrementalMarking() {
return incremental_marking()->IsStopped() &&
incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull();
incremental_marking()->ShouldActivate();
}
......@@ -4573,6 +4572,7 @@ bool Heap::IdleNotification(double deadline_in_seconds) {
static_cast<double>(base::Time::kMillisecondsPerSecond);
HistogramTimerScope idle_notification_scope(
isolate_->counters()->gc_idle_notification());
double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs();
GCIdleTimeHandler::HeapState heap_state;
heap_state.contexts_disposed = contexts_disposed_;
......@@ -4581,8 +4581,15 @@ bool Heap::IdleNotification(double deadline_in_seconds) {
heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
// TODO(ulan): Start incremental marking only for large heaps.
intptr_t limit = old_generation_allocation_limit_;
if (static_cast<size_t>(idle_time_in_ms) >
GCIdleTimeHandler::kMaxFrameRenderingIdleTime) {
limit = idle_old_generation_allocation_limit_;
}
heap_state.can_start_incremental_marking =
incremental_marking()->ShouldActivate() && FLAG_incremental_marking &&
incremental_marking()->WorthActivating() &&
NextGCIsLikelyToBeFull(limit) && FLAG_incremental_marking &&
!mark_compact_collector()->sweeping_in_progress();
heap_state.sweeping_in_progress =
mark_compact_collector()->sweeping_in_progress();
......@@ -4603,7 +4610,6 @@ bool Heap::IdleNotification(double deadline_in_seconds) {
static_cast<size_t>(
tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs();
GCIdleTimeAction action =
gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);
isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(
......@@ -5192,21 +5198,37 @@ int64_t Heap::PromotedExternalMemorySize() {
}
intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size,
int freed_global_handles) {
intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor,
intptr_t old_gen_size) {
CHECK(factor > 1.0);
CHECK(old_gen_size > 0);
intptr_t limit = static_cast<intptr_t>(old_gen_size * factor);
limit = Max(limit, kMinimumOldGenerationAllocationLimit);
limit += new_space_.Capacity();
intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2;
return Min(limit, halfway_to_the_max);
}
void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size,
int freed_global_handles) {
const int kMaxHandles = 1000;
const int kMinHandles = 100;
double min_factor = 1.1;
const double min_factor = 1.1;
double max_factor = 4;
const double idle_max_factor = 1.5;
// We set the old generation growing factor to 2 to grow the heap slower on
// memory-constrained devices.
if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) {
max_factor = 2;
}
// If there are many freed global handles, then the next full GC will
// likely collect a lot of garbage. Choose the heap growing factor
// depending on freed global handles.
// TODO(ulan, hpayer): Take into account mutator utilization.
// TODO(hpayer): The idle factor could make the handles heuristic obsolete.
// Look into that.
double factor;
if (freed_global_handles <= kMinHandles) {
factor = max_factor;
......@@ -5225,11 +5247,10 @@ intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size,
factor = min_factor;
}
intptr_t limit = static_cast<intptr_t>(old_gen_size * factor);
limit = Max(limit, kMinimumOldGenerationAllocationLimit);
limit += new_space_.Capacity();
intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2;
return Min(limit, halfway_to_the_max);
old_generation_allocation_limit_ =
CalculateOldGenerationAllocationLimit(factor, old_gen_size);
idle_old_generation_allocation_limit_ = CalculateOldGenerationAllocationLimit(
Min(factor, idle_max_factor), old_gen_size);
}
......
......@@ -634,6 +634,10 @@ class Heap {
// Returns of size of all objects residing in the heap.
intptr_t SizeOfObjects();
intptr_t old_generation_allocation_limit() const {
return old_generation_allocation_limit_;
}
// Return the starting address and a mask for the new space. And-masking an
// address with the mask will result in the start address of the new space
// for all addresses in either semispace.
......@@ -1120,8 +1124,14 @@ class Heap {
static const int kMaxExecutableSizeHugeMemoryDevice =
256 * kPointerMultiplier;
intptr_t OldGenerationAllocationLimit(intptr_t old_gen_size,
int freed_global_handles);
// Calculates the allocation limit based on a given growing factor and a
// given old generation size.
intptr_t CalculateOldGenerationAllocationLimit(double factor,
intptr_t old_gen_size);
// Sets the allocation limit to trigger the next full garbage collection.
void SetOldGenerationAllocationLimit(intptr_t old_gen_size,
int freed_global_handles);
// Indicates whether inline bump-pointer allocation has been disabled.
bool inline_allocation_disabled() { return inline_allocation_disabled_; }
......@@ -1231,13 +1241,12 @@ class Heap {
survived_since_last_expansion_ += survived;
}
inline bool NextGCIsLikelyToBeFull() {
inline bool NextGCIsLikelyToBeFull(intptr_t limit) {
if (FLAG_gc_global) return true;
if (FLAG_stress_compaction && (gc_count_ & 1) != 0) return true;
intptr_t adjusted_allocation_limit =
old_generation_allocation_limit_ - new_space_.Capacity();
intptr_t adjusted_allocation_limit = limit - new_space_.Capacity();
if (PromotedTotalSize() >= adjusted_allocation_limit) return true;
......@@ -1640,6 +1649,10 @@ class Heap {
// generation and on every allocation in large object space.
intptr_t old_generation_allocation_limit_;
// The allocation limit when there is >16.66ms idle time in the idle time
// handler.
intptr_t idle_old_generation_allocation_limit_;
// Indicates that an allocation has failed in the old generation since the
// last GC.
bool old_gen_exhausted_;
......
......@@ -387,7 +387,9 @@ void IncrementalMarking::ActivateIncrementalWriteBarrier() {
bool IncrementalMarking::ShouldActivate() {
return WorthActivating() && heap_->NextGCIsLikelyToBeFull();
return WorthActivating() &&
heap_->NextGCIsLikelyToBeFull(
heap_->old_generation_allocation_limit());
}
......
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