result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed;
result.available_new_space_memory = kNewSpaceCapacity;
result.new_space_capacity = kNewSpaceCapacity;
+ result.new_space_allocation_throughput_in_bytes_per_ms =
+ kNewSpaceAllocationThroughput;
return result;
}
static const size_t kMarkingSpeed = 200 * KB;
static const size_t kScavengeSpeed = 100 * KB;
static const size_t kNewSpaceCapacity = 1 * MB;
+ static const size_t kNewSpaceAllocationThroughput = 10 * KB;
private:
GCIdleTimeHandler handler_;
}
+TEST(GCIdleTimeHandler, ScavangeMayHappenSoonInitial) {
+ size_t available = 100 * KB;
+ EXPECT_FALSE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, 0));
+}
+
+
+TEST(GCIdleTimeHandler, ScavangeMayHappenSoonNonZeroFalse) {
+ size_t available = (GCIdleTimeHandler::kMaxFrameRenderingIdleTime + 1) * KB;
+ size_t speed = 1 * KB;
+ EXPECT_FALSE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, speed));
+}
+
+
+TEST(GCIdleTimeHandler, ScavangeMayHappenSoonNonZeroTrue) {
+ size_t available = GCIdleTimeHandler::kMaxFrameRenderingIdleTime * KB;
+ size_t speed = 1 * KB;
+ EXPECT_TRUE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, speed));
+}
+
+
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeIdleTime) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.contexts_disposed = 1;
EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
}
+
+TEST_F(GCIdleTimeHandlerTest, Scavenge) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+ int idle_time_ms = 10;
+ heap_state.available_new_space_memory =
+ kNewSpaceAllocationThroughput * idle_time_ms;
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_SCAVENGE, action.type);
+}
+
+
+TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+ int idle_time_ms = 10;
+ heap_state.can_start_incremental_marking = false;
+ heap_state.incremental_marking_stopped = true;
+ heap_state.available_new_space_memory =
+ kNewSpaceAllocationThroughput * idle_time_ms;
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_SCAVENGE, action.type);
+ heap_state.available_new_space_memory = kNewSpaceCapacity;
+ action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
+}
+
} // namespace internal
} // namespace v8
}
+bool GCIdleTimeHandler::ScavangeMayHappenSoon(
+ size_t available_new_space_memory,
+ size_t new_space_allocation_throughput_in_bytes_per_ms) {
+ if (available_new_space_memory <=
+ new_space_allocation_throughput_in_bytes_per_ms *
+ kMaxFrameRenderingIdleTime) {
+ return true;
+ }
+ return false;
+}
+
+
// The following logic is implemented by the controller:
// (1) If the new space is almost full and we can effort a Scavenge, then a
// Scavenge is performed.
// that this currently may trigger a full garbage collection.
GCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms,
HeapState heap_state) {
- if (heap_state.available_new_space_memory < kNewSpaceAlmostFullTreshold &&
+ if (ScavangeMayHappenSoon(
+ heap_state.available_new_space_memory,
+ heap_state.new_space_allocation_throughput_in_bytes_per_ms) &&
idle_time_in_ms >=
EstimateScavengeTime(heap_state.new_space_capacity,
heap_state.scavenge_speed_in_bytes_per_ms)) {
size_t scavenge_speed_in_bytes_per_ms;
size_t available_new_space_memory;
size_t new_space_capacity;
+ size_t new_space_allocation_throughput_in_bytes_per_ms;
};
GCIdleTimeHandler()
static size_t EstimateScavengeTime(size_t new_space_size,
size_t scavenger_speed_in_bytes_per_ms);
+ static bool ScavangeMayHappenSoon(
+ size_t available_new_space_memory,
+ size_t new_space_allocation_throughput_in_bytes_per_ms);
+
private:
void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
bool IsMarkCompactIdleRoundFinished() {