1e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved. 2e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 3e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org// found in the LICENSE file. 4e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 5e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org#include "src/heap/gc-idle-time-handler.h" 6a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/heap/gc-tracer.h" 7a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/utils.h" 8e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 9e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.orgnamespace v8 { 10e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.orgnamespace internal { 11e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 12e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.orgconst double GCIdleTimeHandler::kConservativeTimeRatio = 0.9; 139e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.orgconst size_t GCIdleTimeHandler::kMaxMarkCompactTimeInMs = 1000; 14a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgconst size_t GCIdleTimeHandler::kMinTimeForFinalizeSweeping = 100; 15a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgconst int GCIdleTimeHandler::kMaxMarkCompactsInIdleRound = 7; 16a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgconst int GCIdleTimeHandler::kIdleScavengeThreshold = 5; 17e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 18e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 19ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgvoid GCIdleTimeAction::Print() { 20ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org switch (type) { 21d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org case DONE: 22d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org PrintF("done"); 23d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org break; 24ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org case DO_NOTHING: 25ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org PrintF("no action"); 26ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org break; 27ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org case DO_INCREMENTAL_MARKING: 28ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org PrintF("incremental marking with step %" V8_PTR_PREFIX "d", parameter); 29ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org break; 30ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org case DO_SCAVENGE: 31ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org PrintF("scavenge"); 32ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org break; 33ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org case DO_FULL_GC: 34ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org PrintF("full GC"); 35ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org break; 36ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org case DO_FINALIZE_SWEEPING: 37ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org PrintF("finalize sweeping"); 38ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org break; 39ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org } 40ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org} 41ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org 42ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org 43e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.orgsize_t GCIdleTimeHandler::EstimateMarkingStepSize( 44e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org size_t idle_time_in_ms, size_t marking_speed_in_bytes_per_ms) { 45e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org DCHECK(idle_time_in_ms > 0); 46e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 47e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org if (marking_speed_in_bytes_per_ms == 0) { 48a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed; 49e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org } 50e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 51e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org size_t marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms; 52e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org if (marking_step_size / marking_speed_in_bytes_per_ms != idle_time_in_ms) { 53e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org // In the case of an overflow we return maximum marking step size. 54a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return kMaximumMarkingStepSize; 55e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org } 56e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 57e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org if (marking_step_size > kMaximumMarkingStepSize) 58e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org return kMaximumMarkingStepSize; 59e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org 60a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return static_cast<size_t>(marking_step_size * kConservativeTimeRatio); 61a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} 62a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 63a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 64a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgsize_t GCIdleTimeHandler::EstimateMarkCompactTime( 65a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms) { 66a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (mark_compact_speed_in_bytes_per_ms == 0) { 67a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org mark_compact_speed_in_bytes_per_ms = kInitialConservativeMarkCompactSpeed; 68a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 69a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org size_t result = size_of_objects / mark_compact_speed_in_bytes_per_ms; 70a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return Min(result, kMaxMarkCompactTimeInMs); 71a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} 72a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 73a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 74d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.orgsize_t GCIdleTimeHandler::EstimateScavengeTime( 75d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org size_t new_space_size, size_t scavenge_speed_in_bytes_per_ms) { 76d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (scavenge_speed_in_bytes_per_ms == 0) { 77d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org scavenge_speed_in_bytes_per_ms = kInitialConservativeScavengeSpeed; 78d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org } 79d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org return new_space_size / scavenge_speed_in_bytes_per_ms; 80d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org} 81d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org 82d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org 83a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgbool GCIdleTimeHandler::ScavangeMayHappenSoon( 84a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org size_t available_new_space_memory, 85a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org size_t new_space_allocation_throughput_in_bytes_per_ms) { 86a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (available_new_space_memory <= 87a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org new_space_allocation_throughput_in_bytes_per_ms * 88a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org kMaxFrameRenderingIdleTime) { 89a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org return true; 90a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org } 91a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org return false; 92a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org} 93a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 94a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 95d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// The following logic is implemented by the controller: 96d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// (1) If the new space is almost full and we can effort a Scavenge, then a 97d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// Scavenge is performed. 98d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// (2) If there is currently no MarkCompact idle round going on, we start a 99d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// new idle round if enough garbage was created or we received a context 100d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// disposal event. Otherwise we do not perform garbage collection to keep 101d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// system utilization low. 102d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// (3) If incremental marking is done, we perform a full garbage collection 103d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// if context was disposed or if we are allowed to still do full garbage 104d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// collections during this idle round or if we are not allowed to start 105d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// incremental marking. Otherwise we do not perform garbage collection to 106d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// keep system utilization low. 107d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// (4) If sweeping is in progress and we received a large enough idle time 108d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// request, we finalize sweeping here. 109d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// (5) If incremental marking is in progress, we perform a marking step. Note, 110d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org// that this currently may trigger a full garbage collection. 111a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgGCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms, 112a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org HeapState heap_state) { 113a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (idle_time_in_ms <= kMaxFrameRenderingIdleTime && 114a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org ScavangeMayHappenSoon( 115a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org heap_state.available_new_space_memory, 116a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org heap_state.new_space_allocation_throughput_in_bytes_per_ms) && 117d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org idle_time_in_ms >= 118d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org EstimateScavengeTime(heap_state.new_space_capacity, 119d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org heap_state.scavenge_speed_in_bytes_per_ms)) { 120d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org return GCIdleTimeAction::Scavenge(); 121d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org } 122d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (IsMarkCompactIdleRoundFinished()) { 123a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (EnoughGarbageSinceLastIdleRound() || heap_state.contexts_disposed > 0) { 124a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org StartIdleRound(); 125a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } else { 126d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org return GCIdleTimeAction::Done(); 127a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 128a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 129d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org 130a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org if (idle_time_in_ms == 0) { 131a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org return GCIdleTimeAction::Nothing(); 132a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org } 133a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org 134a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (heap_state.incremental_marking_stopped) { 1359e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org size_t estimated_time_in_ms = 1369e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org EstimateMarkCompactTime(heap_state.size_of_objects, 1379e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org heap_state.mark_compact_speed_in_bytes_per_ms); 1389e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org if (idle_time_in_ms >= estimated_time_in_ms || 1396313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org (heap_state.size_of_objects < kSmallHeapSize && 1406313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org heap_state.contexts_disposed > 0)) { 141a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // If there are no more than two GCs left in this idle round and we are 142a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // allowed to do a full GC, then make those GCs full in order to compact 143a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // the code space. 144a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // TODO(ulan): Once we enable code compaction for incremental marking, we 145a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // can get rid of this special case and always start incremental marking. 146a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org int remaining_mark_sweeps = 147a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org kMaxMarkCompactsInIdleRound - mark_compacts_since_idle_round_started_; 148d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (heap_state.contexts_disposed > 0 || 149d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org (idle_time_in_ms > kMaxFrameRenderingIdleTime && 150d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org (remaining_mark_sweeps <= 2 || 151d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org !heap_state.can_start_incremental_marking))) { 152a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return GCIdleTimeAction::FullGC(); 153a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 154a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 155a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (!heap_state.can_start_incremental_marking) { 156a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return GCIdleTimeAction::Nothing(); 157a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 158a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 159a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // TODO(hpayer): Estimate finalize sweeping time. 160a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (heap_state.sweeping_in_progress && 161a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org idle_time_in_ms >= kMinTimeForFinalizeSweeping) { 162a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return GCIdleTimeAction::FinalizeSweeping(); 163a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 164a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 165d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org if (heap_state.incremental_marking_stopped && 166d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org !heap_state.can_start_incremental_marking) { 167d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org return GCIdleTimeAction::Nothing(); 168d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org } 169a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org size_t step_size = EstimateMarkingStepSize( 170a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org idle_time_in_ms, heap_state.incremental_marking_speed_in_bytes_per_ms); 171a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org return GCIdleTimeAction::IncrementalMarking(step_size); 172e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org} 173e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org} 174e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org} 175