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/flags.h"
8 #include "src/heap/gc-tracer.h"
9 #include "src/utils/utils.h"
10
11 namespace v8 {
12 namespace internal {
13
14 const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
15 const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
16
Print()17 void GCIdleTimeHeapState::Print() {
18 PrintF("contexts_disposed=%d ", contexts_disposed);
19 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
20 PrintF("size_of_objects=%zu ", size_of_objects);
21 PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
22 }
23
EstimateMarkingStepSize(double idle_time_in_ms,double marking_speed_in_bytes_per_ms)24 size_t GCIdleTimeHandler::EstimateMarkingStepSize(
25 double idle_time_in_ms, double marking_speed_in_bytes_per_ms) {
26 DCHECK_LT(0, idle_time_in_ms);
27
28 if (marking_speed_in_bytes_per_ms == 0) {
29 marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
30 }
31
32 double marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
33 if (marking_step_size >= kMaximumMarkingStepSize) {
34 return kMaximumMarkingStepSize;
35 }
36 return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
37 }
38
ShouldDoContextDisposalMarkCompact(int contexts_disposed,double contexts_disposal_rate,size_t size_of_objects)39 bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
40 int contexts_disposed, double contexts_disposal_rate,
41 size_t size_of_objects) {
42 return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
43 contexts_disposal_rate < kHighContextDisposalRate &&
44 size_of_objects <= kMaxHeapSizeForContextDisposalMarkCompact;
45 }
46
47 // The following logic is implemented by the controller:
48 // (1) If we don't have any idle time, do nothing, unless a context was
49 // disposed, incremental marking is stopped, and the heap is small. Then do
50 // a full GC.
51 // (2) If the context disposal rate is high and we cannot perform a full GC,
52 // we do nothing until the context disposal rate becomes lower.
53 // (3) If incremental marking is in progress, we perform a marking step.
Compute(double idle_time_in_ms,GCIdleTimeHeapState heap_state)54 GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
55 GCIdleTimeHeapState heap_state) {
56 if (static_cast<int>(idle_time_in_ms) <= 0) {
57 if (heap_state.incremental_marking_stopped) {
58 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
59 heap_state.contexts_disposal_rate,
60 heap_state.size_of_objects)) {
61 return GCIdleTimeAction::kFullGC;
62 }
63 }
64 return GCIdleTimeAction::kDone;
65 }
66
67 if (FLAG_incremental_marking && !heap_state.incremental_marking_stopped) {
68 return GCIdleTimeAction::kIncrementalStep;
69 }
70
71 return GCIdleTimeAction::kDone;
72 }
73
Enabled()74 bool GCIdleTimeHandler::Enabled() { return FLAG_incremental_marking; }
75
76 } // namespace internal
77 } // namespace v8
78