Commit b105da20 authored by hpayer@chromium.org's avatar hpayer@chromium.org

Allow IdleNotification to trigger Scavenges.

BUG=
R=ulan@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23979 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5d520f9e
......@@ -28,12 +28,17 @@ class GCIdleTimeHandlerTest : public ::testing::Test {
result.sweeping_in_progress = false;
result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed;
result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed;
result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed;
result.available_new_space_memory = kNewSpaceCapacity;
result.new_space_capacity = kNewSpaceCapacity;
return result;
}
static const size_t kSizeOfObjects = 100 * MB;
static const size_t kMarkCompactSpeed = 200 * KB;
static const size_t kMarkingSpeed = 200 * KB;
static const size_t kScavengeSpeed = 100 * KB;
static const size_t kNewSpaceCapacity = 1 * MB;
private:
GCIdleTimeHandler handler_;
......@@ -101,6 +106,21 @@ TEST(GCIdleTimeHandler, EstimateMarkCompactTimeMax) {
}
TEST(GCIdleTimeHandler, EstimateScavengeTimeInitial) {
size_t size = 1 * MB;
size_t time = GCIdleTimeHandler::EstimateScavengeTime(size, 0);
EXPECT_EQ(size / GCIdleTimeHandler::kInitialConservativeScavengeSpeed, time);
}
TEST(GCIdleTimeHandler, EstimateScavengeTimeNonZero) {
size_t size = 1 * MB;
size_t speed = 1 * MB;
size_t time = GCIdleTimeHandler::EstimateScavengeTime(size, speed);
EXPECT_EQ(size / speed, time);
}
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeIdleTime) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.contexts_disposed = 1;
......
......@@ -71,9 +71,40 @@ size_t GCIdleTimeHandler::EstimateMarkCompactTime(
}
size_t GCIdleTimeHandler::EstimateScavengeTime(
size_t new_space_size, size_t scavenge_speed_in_bytes_per_ms) {
if (scavenge_speed_in_bytes_per_ms == 0) {
scavenge_speed_in_bytes_per_ms = kInitialConservativeScavengeSpeed;
}
return new_space_size / scavenge_speed_in_bytes_per_ms;
}
// 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.
// (2) If there is currently no MarkCompact idle round going on, we start a
// new idle round if enough garbage was created or we received a context
// disposal event. Otherwise we do not perform garbage collection to keep
// system utilization low.
// (3) If incremental marking is done, we perform a full garbage collection
// if context was disposed or if we are allowed to still do full garbage
// collections during this idle round or if we are not allowed to start
// incremental marking. Otherwise we do not perform garbage collection to
// keep system utilization low.
// (4) If sweeping is in progress and we received a large enough idle time
// request, we finalize sweeping here.
// (5) If incremental marking is in progress, we perform a marking step. Note,
// that this currently may trigger a full garbage collection.
GCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms,
HeapState heap_state) {
if (IsIdleRoundFinished()) {
if (heap_state.available_new_space_memory < kNewSpaceAlmostFullTreshold &&
idle_time_in_ms >=
EstimateScavengeTime(heap_state.new_space_capacity,
heap_state.scavenge_speed_in_bytes_per_ms)) {
return GCIdleTimeAction::Scavenge();
}
if (IsMarkCompactIdleRoundFinished()) {
if (EnoughGarbageSinceLastIdleRound() || heap_state.contexts_disposed > 0) {
StartIdleRound();
} else {
......
......@@ -113,6 +113,14 @@ class GCIdleTimeHandler {
// That is the maximum idle time we will have during frame rendering.
static const size_t kMaxFrameRenderingIdleTime = 16;
// If less than that much memory is left in the new space, we consider it
// as almost full and force a new space collection earlier in the idle time.
static const size_t kNewSpaceAlmostFullTreshold = 100 * KB;
// If we haven't recorded any scavenger events yet, we use a conservative
// lower bound for the scavenger speed.
static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
struct HeapState {
int contexts_disposed;
size_t size_of_objects;
......@@ -121,6 +129,9 @@ class GCIdleTimeHandler {
bool sweeping_in_progress;
size_t mark_compact_speed_in_bytes_per_ms;
size_t incremental_marking_speed_in_bytes_per_ms;
size_t scavenge_speed_in_bytes_per_ms;
size_t available_new_space_memory;
size_t new_space_capacity;
};
GCIdleTimeHandler()
......@@ -147,9 +158,12 @@ class GCIdleTimeHandler {
static size_t EstimateMarkCompactTime(
size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
static size_t EstimateScavengeTime(size_t new_space_size,
size_t scavenger_speed_in_bytes_per_ms);
private:
void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
bool IsIdleRoundFinished() {
bool IsMarkCompactIdleRoundFinished() {
return mark_compacts_since_idle_round_started_ ==
kMaxMarkCompactsInIdleRound;
}
......
......@@ -4311,6 +4311,10 @@ bool Heap::IdleNotification(int idle_time_in_ms) {
static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond());
heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>(
tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
heap_state.scavenge_speed_in_bytes_per_ms =
static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond());
heap_state.available_new_space_memory = new_space_.Available();
heap_state.new_space_capacity = new_space_.Capacity();
GCIdleTimeAction action =
gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);
......
......@@ -2013,7 +2013,7 @@ class NewSpacePage : public MemoryChunk {
Address address() { return reinterpret_cast<Address>(this); }
// Finds the NewSpacePage containg the given address.
// Finds the NewSpacePage containing the given address.
static inline NewSpacePage* FromAddress(Address address_in_page) {
Address page_start =
reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) &
......
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