1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_HEAP_GC_IDLE_TIME_HANDLER_H_
6 #define V8_HEAP_GC_IDLE_TIME_HANDLER_H_
8 #include "src/globals.h"
13 enum GCIdleTimeActionType {
16 DO_INCREMENTAL_MARKING,
23 class GCIdleTimeAction {
25 static GCIdleTimeAction Done() {
26 GCIdleTimeAction result;
29 result.additional_work = false;
33 static GCIdleTimeAction Nothing() {
34 GCIdleTimeAction result;
35 result.type = DO_NOTHING;
37 result.additional_work = false;
41 static GCIdleTimeAction IncrementalMarking(intptr_t step_size) {
42 GCIdleTimeAction result;
43 result.type = DO_INCREMENTAL_MARKING;
44 result.parameter = step_size;
45 result.additional_work = false;
49 static GCIdleTimeAction Scavenge() {
50 GCIdleTimeAction result;
51 result.type = DO_SCAVENGE;
53 result.additional_work = false;
57 static GCIdleTimeAction FullGC() {
58 GCIdleTimeAction result;
59 result.type = DO_FULL_GC;
61 result.additional_work = false;
65 static GCIdleTimeAction FinalizeSweeping() {
66 GCIdleTimeAction result;
67 result.type = DO_FINALIZE_SWEEPING;
69 result.additional_work = false;
75 GCIdleTimeActionType type;
83 // The idle time handler makes decisions about which garbage collection
84 // operations are executing during IdleNotification.
85 class GCIdleTimeHandler {
87 // If we haven't recorded any incremental marking events yet, we carefully
88 // mark with a conservative lower bound for the marking speed.
89 static const size_t kInitialConservativeMarkingSpeed = 100 * KB;
91 // Maximum marking step size returned by EstimateMarkingStepSize.
92 static const size_t kMaximumMarkingStepSize = 700 * MB;
94 // We have to make sure that we finish the IdleNotification before
95 // idle_time_in_ms. Hence, we conservatively prune our workload estimate.
96 static const double kConservativeTimeRatio;
98 // If we haven't recorded any mark-compact events yet, we use
99 // conservative lower bound for the mark-compact speed.
100 static const size_t kInitialConservativeMarkCompactSpeed = 2 * MB;
102 // If we haven't recorded any final incremental mark-compact events yet, we
103 // use conservative lower bound for the mark-compact speed.
104 static const size_t kInitialConservativeFinalIncrementalMarkCompactSpeed =
107 // Maximum mark-compact time returned by EstimateMarkCompactTime.
108 static const size_t kMaxMarkCompactTimeInMs;
110 // Maximum final incremental mark-compact time returned by
111 // EstimateFinalIncrementalMarkCompactTime.
112 static const size_t kMaxFinalIncrementalMarkCompactTimeInMs;
114 // Minimum time to finalize sweeping phase. The main thread may wait for
116 static const size_t kMinTimeForFinalizeSweeping;
118 // Number of idle mark-compact events, after which idle handler will finish
120 static const int kMaxMarkCompactsInIdleRound;
122 // Number of scavenges that will trigger start of new idle round.
123 static const int kIdleScavengeThreshold;
125 // This is the maximum scheduled idle time. Note that it can be more than
126 // 16.66 ms when there is currently no rendering going on.
127 static const size_t kMaxScheduledIdleTime = 50;
129 // The maximum idle time when frames are rendered is 16.66ms.
130 static const size_t kMaxFrameRenderingIdleTime = 17;
132 // lower bound for the scavenger speed.
133 static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
135 // If contexts are disposed at a higher rate a full gc is triggered.
136 static const double kHighContextDisposalRate;
138 // Incremental marking step time.
139 static const size_t kIncrementalMarkingStepTimeInMs = 1;
141 static const size_t kMinTimeForOverApproximatingWeakClosureInMs;
143 // Number of times we will return a Nothing action per Idle round despite
144 // having idle time available before we returning a Done action to ensure we
145 // don't keep scheduling idle tasks and making no progress.
146 static const int kMaxNoProgressIdleTimesPerIdleRound = 10;
152 int contexts_disposed;
153 double contexts_disposal_rate;
154 size_t size_of_objects;
155 bool incremental_marking_stopped;
156 bool can_start_incremental_marking;
157 bool sweeping_in_progress;
158 size_t mark_compact_speed_in_bytes_per_ms;
159 size_t incremental_marking_speed_in_bytes_per_ms;
160 size_t final_incremental_mark_compact_speed_in_bytes_per_ms;
161 size_t scavenge_speed_in_bytes_per_ms;
162 size_t used_new_space_size;
163 size_t new_space_capacity;
164 size_t new_space_allocation_throughput_in_bytes_per_ms;
168 : mark_compacts_since_idle_round_started_(0),
169 scavenges_since_last_idle_round_(0),
170 idle_times_which_made_no_progress_since_last_idle_round_(0) {}
172 GCIdleTimeAction Compute(double idle_time_in_ms, HeapState heap_state);
174 void NotifyIdleMarkCompact() {
175 if (mark_compacts_since_idle_round_started_ < kMaxMarkCompactsInIdleRound) {
176 ++mark_compacts_since_idle_round_started_;
177 if (mark_compacts_since_idle_round_started_ ==
178 kMaxMarkCompactsInIdleRound) {
179 scavenges_since_last_idle_round_ = 0;
184 void NotifyScavenge() { ++scavenges_since_last_idle_round_; }
186 static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
187 size_t marking_speed_in_bytes_per_ms);
189 static size_t EstimateMarkCompactTime(
190 size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
192 static size_t EstimateFinalIncrementalMarkCompactTime(
193 size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
195 static bool ShouldDoMarkCompact(size_t idle_time_in_ms,
196 size_t size_of_objects,
197 size_t mark_compact_speed_in_bytes_per_ms);
199 static bool ShouldDoContextDisposalMarkCompact(int context_disposed,
200 double contexts_disposal_rate);
202 static bool ShouldDoFinalIncrementalMarkCompact(
203 size_t idle_time_in_ms, size_t size_of_objects,
204 size_t final_incremental_mark_compact_speed_in_bytes_per_ms);
206 static bool ShouldDoOverApproximateWeakClosure(size_t idle_time_in_ms);
208 static bool ShouldDoScavenge(
209 size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size,
210 size_t scavenger_speed_in_bytes_per_ms,
211 size_t new_space_allocation_throughput_in_bytes_per_ms);
214 GCIdleTimeAction NothingOrDone();
216 void StartIdleRound() {
217 mark_compacts_since_idle_round_started_ = 0;
218 idle_times_which_made_no_progress_since_last_idle_round_ = 0;
220 bool IsMarkCompactIdleRoundFinished() {
221 return mark_compacts_since_idle_round_started_ ==
222 kMaxMarkCompactsInIdleRound;
224 bool EnoughGarbageSinceLastIdleRound() {
225 return scavenges_since_last_idle_round_ >= kIdleScavengeThreshold;
228 int mark_compacts_since_idle_round_started_;
229 int scavenges_since_last_idle_round_;
230 int idle_times_which_made_no_progress_since_last_idle_round_;
232 DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
235 } // namespace internal
238 #endif // V8_HEAP_GC_IDLE_TIME_HANDLER_H_