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 #ifndef V8_HEAP_GC_IDLE_TIME_HANDLER_H_ 6 #define V8_HEAP_GC_IDLE_TIME_HANDLER_H_ 7 8 #include "src/globals.h" 9 10 namespace v8 { 11 namespace internal { 12 13 enum GCIdleTimeActionType { 14 DONE, 15 DO_NOTHING, 16 DO_INCREMENTAL_STEP, 17 DO_FULL_GC, 18 }; 19 20 21 class GCIdleTimeAction { 22 public: Done()23 static GCIdleTimeAction Done() { 24 GCIdleTimeAction result; 25 result.type = DONE; 26 result.additional_work = false; 27 return result; 28 } 29 Nothing()30 static GCIdleTimeAction Nothing() { 31 GCIdleTimeAction result; 32 result.type = DO_NOTHING; 33 result.additional_work = false; 34 return result; 35 } 36 IncrementalStep()37 static GCIdleTimeAction IncrementalStep() { 38 GCIdleTimeAction result; 39 result.type = DO_INCREMENTAL_STEP; 40 result.additional_work = false; 41 return result; 42 } 43 FullGC()44 static GCIdleTimeAction FullGC() { 45 GCIdleTimeAction result; 46 result.type = DO_FULL_GC; 47 result.additional_work = false; 48 return result; 49 } 50 51 void Print(); 52 53 GCIdleTimeActionType type; 54 bool additional_work; 55 }; 56 57 58 class GCIdleTimeHeapState { 59 public: 60 void Print(); 61 62 int contexts_disposed; 63 double contexts_disposal_rate; 64 size_t size_of_objects; 65 bool incremental_marking_stopped; 66 }; 67 68 69 // The idle time handler makes decisions about which garbage collection 70 // operations are executing during IdleNotification. 71 class GCIdleTimeHandler { 72 public: 73 // If we haven't recorded any incremental marking events yet, we carefully 74 // mark with a conservative lower bound for the marking speed. 75 static const size_t kInitialConservativeMarkingSpeed = 100 * KB; 76 77 // Maximum marking step size returned by EstimateMarkingStepSize. 78 static const size_t kMaximumMarkingStepSize = 700 * MB; 79 80 // We have to make sure that we finish the IdleNotification before 81 // idle_time_in_ms. Hence, we conservatively prune our workload estimate. 82 static const double kConservativeTimeRatio; 83 84 // If we haven't recorded any mark-compact events yet, we use 85 // conservative lower bound for the mark-compact speed. 86 static const size_t kInitialConservativeMarkCompactSpeed = 2 * MB; 87 88 // If we haven't recorded any final incremental mark-compact events yet, we 89 // use conservative lower bound for the mark-compact speed. 90 static const size_t kInitialConservativeFinalIncrementalMarkCompactSpeed = 91 2 * MB; 92 93 // Maximum mark-compact time returned by EstimateMarkCompactTime. 94 static const size_t kMaxMarkCompactTimeInMs; 95 96 // Maximum final incremental mark-compact time returned by 97 // EstimateFinalIncrementalMarkCompactTime. 98 static const size_t kMaxFinalIncrementalMarkCompactTimeInMs; 99 100 // This is the maximum scheduled idle time. Note that it can be more than 101 // 16.66 ms when there is currently no rendering going on. 102 static const size_t kMaxScheduledIdleTime = 50; 103 104 // The maximum idle time when frames are rendered is 16.66ms. 105 static const size_t kMaxFrameRenderingIdleTime = 17; 106 107 static const int kMinBackgroundIdleTime = 900; 108 109 // An allocation throughput below kLowAllocationThroughput bytes/ms is 110 // considered low 111 static const size_t kLowAllocationThroughput = 1000; 112 113 // If contexts are disposed at a higher rate a full gc is triggered. 114 static const double kHighContextDisposalRate; 115 116 // Incremental marking step time. 117 static const size_t kIncrementalMarkingStepTimeInMs = 1; 118 119 static const size_t kMinTimeForOverApproximatingWeakClosureInMs; 120 121 // Number of times we will return a Nothing action in the current mode 122 // despite having idle time available before we returning a Done action to 123 // ensure we don't keep scheduling idle tasks and making no progress. 124 static const int kMaxNoProgressIdleTimes = 10; 125 GCIdleTimeHandler()126 GCIdleTimeHandler() : idle_times_which_made_no_progress_(0) {} 127 128 GCIdleTimeAction Compute(double idle_time_in_ms, 129 GCIdleTimeHeapState heap_state); 130 ResetNoProgressCounter()131 void ResetNoProgressCounter() { idle_times_which_made_no_progress_ = 0; } 132 133 static size_t EstimateMarkingStepSize(size_t idle_time_in_ms, 134 size_t marking_speed_in_bytes_per_ms); 135 136 static size_t EstimateMarkCompactTime( 137 size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms); 138 139 static size_t EstimateFinalIncrementalMarkCompactTime( 140 size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms); 141 142 static bool ShouldDoMarkCompact(size_t idle_time_in_ms, 143 size_t size_of_objects, 144 size_t mark_compact_speed_in_bytes_per_ms); 145 146 static bool ShouldDoContextDisposalMarkCompact(int context_disposed, 147 double contexts_disposal_rate); 148 149 static bool ShouldDoFinalIncrementalMarkCompact( 150 size_t idle_time_in_ms, size_t size_of_objects, 151 size_t final_incremental_mark_compact_speed_in_bytes_per_ms); 152 153 static bool ShouldDoOverApproximateWeakClosure(size_t idle_time_in_ms); 154 155 private: 156 GCIdleTimeAction NothingOrDone(double idle_time_in_ms); 157 158 // Idle notifications with no progress. 159 int idle_times_which_made_no_progress_; 160 161 DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler); 162 }; 163 164 } // namespace internal 165 } // namespace v8 166 167 #endif // V8_HEAP_GC_IDLE_TIME_HANDLER_H_ 168