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