Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Version 4.3.61.2 (cherry-pick)
Browse files Browse the repository at this point in the history
Merged 00477a5

Ensure that GC idle notifications either make progress or stop requesting more GCs.

BUG=chromium:470615
LOG=N
R=hpayer@chromium.org

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

Cr-Commit-Position: refs/branch-heads/4.3@{#3}
Cr-Branched-From: f5c0a23-refs/heads/4.3.61@{#1}
Cr-Branched-From: 0a7d4f4-refs/heads/master@{#27508}
  • Loading branch information
Ross McIlroy committed Apr 8, 2015
1 parent 25a166b commit 79e7295
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
2 changes: 1 addition & 1 deletion include/v8-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 3
#define V8_BUILD_NUMBER 61
#define V8_PATCH_LEVEL 1
#define V8_PATCH_LEVEL 2

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
16 changes: 14 additions & 2 deletions src/heap/gc-idle-time-handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,22 @@ bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
}


GCIdleTimeAction GCIdleTimeHandler::NothingOrDone() {
if (idle_times_which_made_no_progress_since_last_idle_round_ >=
kMaxNoProgressIdleTimesPerIdleRound) {
return GCIdleTimeAction::Done();
} else {
idle_times_which_made_no_progress_since_last_idle_round_++;
return GCIdleTimeAction::Nothing();
}
}


// The following logic is implemented by the controller:
// (1) If we don't have any idle time, do nothing, unless a context was
// disposed, incremental marking is stopped, and the heap is small. Then do
// a full GC.
// (2) If the new space is almost full and we can affort a Scavenge or if the
// (2) If the new space is almost full and we can afford a Scavenge or if the
// next Scavenge will very likely take long, then a Scavenge is performed.
// (3) If there is currently no MarkCompact idle round going on, we start a
// new idle round if enough garbage was created. Otherwise we do not perform
Expand Down Expand Up @@ -249,8 +260,9 @@ GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,

if (heap_state.incremental_marking_stopped &&
!heap_state.can_start_incremental_marking) {
return GCIdleTimeAction::Nothing();
return NothingOrDone();
}

size_t step_size = EstimateMarkingStepSize(
static_cast<size_t>(kIncrementalMarkingStepTimeInMs),
heap_state.incremental_marking_speed_in_bytes_per_ms);
Expand Down
16 changes: 14 additions & 2 deletions src/heap/gc-idle-time-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ class GCIdleTimeHandler {

static const size_t kMinTimeForOverApproximatingWeakClosureInMs;

// Number of times we will return a Nothing action per Idle round despite
// having idle time available before we returning a Done action to ensure we
// don't keep scheduling idle tasks and making no progress.
static const int kMaxNoProgressIdleTimesPerIdleRound = 10;

class HeapState {
public:
void Print();
Expand All @@ -159,7 +164,8 @@ class GCIdleTimeHandler {

GCIdleTimeHandler()
: mark_compacts_since_idle_round_started_(0),
scavenges_since_last_idle_round_(0) {}
scavenges_since_last_idle_round_(0),
idle_times_which_made_no_progress_since_last_idle_round_(0) {}

GCIdleTimeAction Compute(double idle_time_in_ms, HeapState heap_state);

Expand Down Expand Up @@ -203,7 +209,12 @@ class GCIdleTimeHandler {
size_t new_space_allocation_throughput_in_bytes_per_ms);

private:
void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
GCIdleTimeAction NothingOrDone();

void StartIdleRound() {
mark_compacts_since_idle_round_started_ = 0;
idle_times_which_made_no_progress_since_last_idle_round_ = 0;
}
bool IsMarkCompactIdleRoundFinished() {
return mark_compacts_since_idle_round_started_ ==
kMaxMarkCompactsInIdleRound;
Expand All @@ -214,6 +225,7 @@ class GCIdleTimeHandler {

int mark_compacts_since_idle_round_started_;
int scavenges_since_last_idle_round_;
int idle_times_which_made_no_progress_since_last_idle_round_;

DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
};
Expand Down
50 changes: 50 additions & 0 deletions test/unittests/heap/gc-idle-time-handler-unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -440,5 +440,55 @@ TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeDoNothingButStartIdleRound) {
EXPECT_EQ(DO_NOTHING, action.type);
}


TEST_F(GCIdleTimeHandlerTest, KeepDoingDoNothingWithZeroIdleTime) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
i++) {
GCIdleTimeAction action = handler()->Compute(0, heap_state);
EXPECT_EQ(DO_NOTHING, action.type);
}
// Should still return DO_NOTHING if we have been given 0 deadline yet.
GCIdleTimeAction action = handler()->Compute(0, heap_state);
EXPECT_EQ(DO_NOTHING, action.type);
}


TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();

// Simulate sweeping being in-progress but not complete.
heap_state.incremental_marking_stopped = true;
heap_state.can_start_incremental_marking = false;
heap_state.sweeping_in_progress = true;
double idle_time_ms = 10.0;
for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
i++) {
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DO_NOTHING, action.type);
}
// We should return DONE after not making progress for some time.
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
}


TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();

// Simulate incremental marking stopped and not eligible to start.
heap_state.incremental_marking_stopped = true;
heap_state.can_start_incremental_marking = false;
double idle_time_ms = 10.0;
for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound;
i++) {
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DO_NOTHING, action.type);
}
// We should return DONE after not making progress for some time.
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
}

} // namespace internal
} // namespace v8

0 comments on commit 79e7295

Please sign in to comment.