blob: 972dfa6e5cf9ef12165f1b685c63a02e0d321d18 [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;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015const size_t GCIdleTimeHandler::kMaxFinalIncrementalMarkCompactTimeInMs = 1000;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017const size_t GCIdleTimeHandler::kMinTimeForOverApproximatingWeakClosureInMs = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018
19
20void GCIdleTimeAction::Print() {
21 switch (type) {
22 case DONE:
23 PrintF("done");
24 break;
25 case DO_NOTHING:
26 PrintF("no action");
27 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 case DO_INCREMENTAL_STEP:
29 PrintF("incremental step");
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030 if (additional_work) {
31 PrintF("; finalized marking");
32 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 case DO_FULL_GC:
35 PrintF("full GC");
36 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037 }
38}
39
40
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041void GCIdleTimeHeapState::Print() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 PrintF("contexts_disposed=%d ", contexts_disposed);
43 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
Ben Murdochda12d292016-06-02 14:46:10 +010044 PrintF("size_of_objects=%" V8_SIZET_PREFIX V8_PTR_PREFIX "d ",
45 size_of_objects);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046 PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047}
48
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049size_t GCIdleTimeHandler::EstimateMarkingStepSize(
Ben Murdochda12d292016-06-02 14:46:10 +010050 double idle_time_in_ms, double marking_speed_in_bytes_per_ms) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 DCHECK(idle_time_in_ms > 0);
52
53 if (marking_speed_in_bytes_per_ms == 0) {
54 marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
55 }
56
Ben Murdochda12d292016-06-02 14:46:10 +010057 double marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
58 if (marking_step_size >= kMaximumMarkingStepSize) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 return kMaximumMarkingStepSize;
60 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
62}
63
Ben Murdochda12d292016-06-02 14:46:10 +010064double GCIdleTimeHandler::EstimateFinalIncrementalMarkCompactTime(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 size_t size_of_objects,
Ben Murdochda12d292016-06-02 14:46:10 +010066 double final_incremental_mark_compact_speed_in_bytes_per_ms) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067 if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) {
68 final_incremental_mark_compact_speed_in_bytes_per_ms =
69 kInitialConservativeFinalIncrementalMarkCompactSpeed;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 }
Ben Murdochda12d292016-06-02 14:46:10 +010071 double result =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms;
Ben Murdochda12d292016-06-02 14:46:10 +010073 return Min<double>(result, kMaxFinalIncrementalMarkCompactTimeInMs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074}
75
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
77 int contexts_disposed, double contexts_disposal_rate) {
78 return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
79 contexts_disposal_rate < kHighContextDisposalRate;
80}
81
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
Ben Murdochda12d292016-06-02 14:46:10 +010083 double idle_time_in_ms, size_t size_of_objects,
84 double final_incremental_mark_compact_speed_in_bytes_per_ms) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 return idle_time_in_ms >=
86 EstimateFinalIncrementalMarkCompactTime(
87 size_of_objects,
88 final_incremental_mark_compact_speed_in_bytes_per_ms);
89}
90
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
Ben Murdochda12d292016-06-02 14:46:10 +010092 double idle_time_in_ms) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 // TODO(jochen): Estimate the time it will take to build the object groups.
94 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs;
95}
96
97
98GCIdleTimeAction GCIdleTimeHandler::NothingOrDone(double idle_time_in_ms) {
99 if (idle_time_in_ms >= kMinBackgroundIdleTime) {
100 return GCIdleTimeAction::Nothing();
101 }
102 if (idle_times_which_made_no_progress_ >= kMaxNoProgressIdleTimes) {
103 return GCIdleTimeAction::Done();
104 } else {
105 idle_times_which_made_no_progress_++;
106 return GCIdleTimeAction::Nothing();
107 }
108}
109
110
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111// The following logic is implemented by the controller:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112// (1) If we don't have any idle time, do nothing, unless a context was
113// disposed, incremental marking is stopped, and the heap is small. Then do
114// a full GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115// (2) If the context disposal rate is high and we cannot perform a full GC,
116// we do nothing until the context disposal rate becomes lower.
117// (3) If the new space is almost full and we can affort a scavenge or if the
118// next scavenge will very likely take long, then a scavenge is performed.
119// (4) If sweeping is in progress and we received a large enough idle time
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120// request, we finalize sweeping here.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121// (5) If incremental marking is in progress, we perform a marking step. Note,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122// that this currently may trigger a full garbage collection.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 GCIdleTimeHeapState heap_state) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125 if (static_cast<int>(idle_time_in_ms) <= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 if (heap_state.incremental_marking_stopped) {
127 if (ShouldDoContextDisposalMarkCompact(
128 heap_state.contexts_disposed,
129 heap_state.contexts_disposal_rate)) {
130 return GCIdleTimeAction::FullGC();
131 }
132 }
133 return GCIdleTimeAction::Nothing();
134 }
135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 // We are in a context disposal GC scenario. Don't do anything if we do not
137 // get the right idle signal.
138 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
139 heap_state.contexts_disposal_rate)) {
140 return NothingOrDone(idle_time_in_ms);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) {
144 return GCIdleTimeAction::Done();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 }
146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 return GCIdleTimeAction::IncrementalStep();
148}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
151} // namespace internal
152} // namespace v8