Line data Source code
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.
4 :
5 : #include "src/heap/gc-idle-time-handler.h"
6 :
7 : #include "src/flags.h"
8 : #include "src/heap/gc-tracer.h"
9 : #include "src/utils.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
15 : const size_t GCIdleTimeHandler::kMaxFinalIncrementalMarkCompactTimeInMs = 1000;
16 : const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
17 : const size_t GCIdleTimeHandler::kMinTimeForOverApproximatingWeakClosureInMs = 1;
18 :
19 :
20 0 : void GCIdleTimeHeapState::Print() {
21 0 : PrintF("contexts_disposed=%d ", contexts_disposed);
22 0 : PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
23 0 : PrintF("size_of_objects=%" PRIuS " ", size_of_objects);
24 0 : PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
25 0 : }
26 :
27 1098085 : size_t GCIdleTimeHandler::EstimateMarkingStepSize(
28 : double idle_time_in_ms, double marking_speed_in_bytes_per_ms) {
29 : DCHECK_LT(0, idle_time_in_ms);
30 :
31 1098085 : if (marking_speed_in_bytes_per_ms == 0) {
32 : marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
33 : }
34 :
35 1098085 : double marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
36 1098085 : if (marking_step_size >= kMaximumMarkingStepSize) {
37 : return kMaximumMarkingStepSize;
38 : }
39 1093604 : return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
40 : }
41 :
42 0 : double GCIdleTimeHandler::EstimateFinalIncrementalMarkCompactTime(
43 : size_t size_of_objects,
44 : double final_incremental_mark_compact_speed_in_bytes_per_ms) {
45 2 : if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) {
46 : final_incremental_mark_compact_speed_in_bytes_per_ms =
47 : kInitialConservativeFinalIncrementalMarkCompactSpeed;
48 : }
49 : double result =
50 2 : size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms;
51 0 : return Min<double>(result, kMaxFinalIncrementalMarkCompactTimeInMs);
52 : }
53 :
54 0 : bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
55 : int contexts_disposed, double contexts_disposal_rate,
56 : size_t size_of_objects) {
57 268 : return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
58 455 : contexts_disposal_rate < kHighContextDisposalRate &&
59 0 : size_of_objects <= kMaxHeapSizeForContextDisposalMarkCompact;
60 : }
61 :
62 2 : bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
63 : double idle_time_in_ms, size_t size_of_objects,
64 : double final_incremental_mark_compact_speed_in_bytes_per_ms) {
65 : return idle_time_in_ms >=
66 : EstimateFinalIncrementalMarkCompactTime(
67 : size_of_objects,
68 2 : final_incremental_mark_compact_speed_in_bytes_per_ms);
69 : }
70 :
71 0 : bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
72 : double idle_time_in_ms) {
73 : // TODO(jochen): Estimate the time it will take to build the object groups.
74 0 : return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs;
75 : }
76 :
77 :
78 : // The following logic is implemented by the controller:
79 : // (1) If we don't have any idle time, do nothing, unless a context was
80 : // disposed, incremental marking is stopped, and the heap is small. Then do
81 : // a full GC.
82 : // (2) If the context disposal rate is high and we cannot perform a full GC,
83 : // we do nothing until the context disposal rate becomes lower.
84 : // (3) If the new space is almost full and we can afford a scavenge or if the
85 : // next scavenge will very likely take long, then a scavenge is performed.
86 : // (4) If sweeping is in progress and we received a large enough idle time
87 : // request, we finalize sweeping here.
88 : // (5) If incremental marking is in progress, we perform a marking step. Note,
89 : // that this currently may trigger a full garbage collection.
90 491 : GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
91 : GCIdleTimeHeapState heap_state) {
92 491 : if (static_cast<int>(idle_time_in_ms) <= 0) {
93 301 : if (heap_state.incremental_marking_stopped) {
94 536 : if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
95 : heap_state.contexts_disposal_rate,
96 : heap_state.size_of_objects)) {
97 : return GCIdleTimeAction::kFullGC;
98 : }
99 : }
100 : return GCIdleTimeAction::kDone;
101 : }
102 :
103 190 : if (FLAG_incremental_marking && !heap_state.incremental_marking_stopped) {
104 : return GCIdleTimeAction::kIncrementalStep;
105 : }
106 :
107 136 : return GCIdleTimeAction::kDone;
108 : }
109 :
110 11 : bool GCIdleTimeHandler::Enabled() { return FLAG_incremental_marking; }
111 :
112 : } // namespace internal
113 122036 : } // namespace v8
|