blob: 4e6e6081d7bf4e4e7504ae8224c5d510f925d448 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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.
4
5#include "src/heap/gc-idle-time-handler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006
7#include "src/flags.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/heap/gc-tracer.h"
9#include "src/utils.h"
10
11namespace v8 {
12namespace internal {
13
14const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
15const size_t GCIdleTimeHandler::kMaxMarkCompactTimeInMs = 1000;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016const size_t GCIdleTimeHandler::kMaxFinalIncrementalMarkCompactTimeInMs = 1000;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018const size_t GCIdleTimeHandler::kMinTimeForOverApproximatingWeakClosureInMs = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019
20
21void GCIdleTimeAction::Print() {
22 switch (type) {
23 case DONE:
24 PrintF("done");
25 break;
26 case DO_NOTHING:
27 PrintF("no action");
28 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 case DO_INCREMENTAL_STEP:
30 PrintF("incremental step");
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031 if (additional_work) {
32 PrintF("; finalized marking");
33 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 case DO_FULL_GC:
36 PrintF("full GC");
37 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 }
39}
40
41
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042void GCIdleTimeHeapState::Print() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 PrintF("contexts_disposed=%d ", contexts_disposed);
44 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
45 PrintF("size_of_objects=%" V8_PTR_PREFIX "d ", size_of_objects);
46 PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047}
48
49
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050size_t GCIdleTimeHandler::EstimateMarkingStepSize(
51 size_t idle_time_in_ms, size_t marking_speed_in_bytes_per_ms) {
52 DCHECK(idle_time_in_ms > 0);
53
54 if (marking_speed_in_bytes_per_ms == 0) {
55 marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
56 }
57
58 size_t marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
59 if (marking_step_size / marking_speed_in_bytes_per_ms != idle_time_in_ms) {
60 // In the case of an overflow we return maximum marking step size.
61 return kMaximumMarkingStepSize;
62 }
63
64 if (marking_step_size > kMaximumMarkingStepSize)
65 return kMaximumMarkingStepSize;
66
67 return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
68}
69
70
71size_t GCIdleTimeHandler::EstimateMarkCompactTime(
72 size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073 // TODO(hpayer): Be more precise about the type of mark-compact event. It
74 // makes a huge difference if compaction is happening.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 if (mark_compact_speed_in_bytes_per_ms == 0) {
76 mark_compact_speed_in_bytes_per_ms = kInitialConservativeMarkCompactSpeed;
77 }
78 size_t result = size_of_objects / mark_compact_speed_in_bytes_per_ms;
79 return Min(result, kMaxMarkCompactTimeInMs);
80}
81
82
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083size_t GCIdleTimeHandler::EstimateFinalIncrementalMarkCompactTime(
84 size_t size_of_objects,
85 size_t final_incremental_mark_compact_speed_in_bytes_per_ms) {
86 if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) {
87 final_incremental_mark_compact_speed_in_bytes_per_ms =
88 kInitialConservativeFinalIncrementalMarkCompactSpeed;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090 size_t result =
91 size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms;
92 return Min(result, kMaxFinalIncrementalMarkCompactTimeInMs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093}
94
95
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096bool GCIdleTimeHandler::ShouldDoMarkCompact(
97 size_t idle_time_in_ms, size_t size_of_objects,
98 size_t mark_compact_speed_in_bytes_per_ms) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 return idle_time_in_ms >= kMaxScheduledIdleTime &&
100 idle_time_in_ms >=
101 EstimateMarkCompactTime(size_of_objects,
102 mark_compact_speed_in_bytes_per_ms);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103}
104
105
106bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
107 int contexts_disposed, double contexts_disposal_rate) {
108 return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
109 contexts_disposal_rate < kHighContextDisposalRate;
110}
111
112
113bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
114 size_t idle_time_in_ms, size_t size_of_objects,
115 size_t final_incremental_mark_compact_speed_in_bytes_per_ms) {
116 return idle_time_in_ms >=
117 EstimateFinalIncrementalMarkCompactTime(
118 size_of_objects,
119 final_incremental_mark_compact_speed_in_bytes_per_ms);
120}
121
122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
124 size_t idle_time_in_ms) {
125 // TODO(jochen): Estimate the time it will take to build the object groups.
126 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs;
127}
128
129
130GCIdleTimeAction GCIdleTimeHandler::NothingOrDone(double idle_time_in_ms) {
131 if (idle_time_in_ms >= kMinBackgroundIdleTime) {
132 return GCIdleTimeAction::Nothing();
133 }
134 if (idle_times_which_made_no_progress_ >= kMaxNoProgressIdleTimes) {
135 return GCIdleTimeAction::Done();
136 } else {
137 idle_times_which_made_no_progress_++;
138 return GCIdleTimeAction::Nothing();
139 }
140}
141
142
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143// The following logic is implemented by the controller:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144// (1) If we don't have any idle time, do nothing, unless a context was
145// disposed, incremental marking is stopped, and the heap is small. Then do
146// a full GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147// (2) If the context disposal rate is high and we cannot perform a full GC,
148// we do nothing until the context disposal rate becomes lower.
149// (3) If the new space is almost full and we can affort a scavenge or if the
150// next scavenge will very likely take long, then a scavenge is performed.
151// (4) If sweeping is in progress and we received a large enough idle time
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152// request, we finalize sweeping here.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153// (5) If incremental marking is in progress, we perform a marking step. Note,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154// that this currently may trigger a full garbage collection.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 GCIdleTimeHeapState heap_state) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400157 if (static_cast<int>(idle_time_in_ms) <= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158 if (heap_state.incremental_marking_stopped) {
159 if (ShouldDoContextDisposalMarkCompact(
160 heap_state.contexts_disposed,
161 heap_state.contexts_disposal_rate)) {
162 return GCIdleTimeAction::FullGC();
163 }
164 }
165 return GCIdleTimeAction::Nothing();
166 }
167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 // We are in a context disposal GC scenario. Don't do anything if we do not
169 // get the right idle signal.
170 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
171 heap_state.contexts_disposal_rate)) {
172 return NothingOrDone(idle_time_in_ms);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) {
176 return GCIdleTimeAction::Done();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 }
178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 return GCIdleTimeAction::IncrementalStep();
180}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182
183} // namespace internal
184} // namespace v8