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 final incremental mark-compact time returned by 94 // EstimateFinalIncrementalMarkCompactTime. 95 static const size_t kMaxFinalIncrementalMarkCompactTimeInMs; 96 97 // This is the maximum scheduled idle time. Note that it can be more than 98 // 16.66 ms when there is currently no rendering going on. 99 static const size_t kMaxScheduledIdleTime = 50; 100 101 // The maximum idle time when frames are rendered is 16.66ms. 102 static const size_t kMaxFrameRenderingIdleTime = 17; 103 104 static const int kMinBackgroundIdleTime = 900; 105 106 // An allocation throughput below kLowAllocationThroughput bytes/ms is 107 // considered low 108 static const size_t kLowAllocationThroughput = 1000; 109 110 // If contexts are disposed at a higher rate a full gc is triggered. 111 static const double kHighContextDisposalRate; 112 113 // Incremental marking step time. 114 static const size_t kIncrementalMarkingStepTimeInMs = 1; 115 116 static const size_t kMinTimeForOverApproximatingWeakClosureInMs; 117 118 // Number of times we will return a Nothing action in the current mode 119 // despite having idle time available before we returning a Done action to 120 // ensure we don't keep scheduling idle tasks and making no progress. 121 static const int kMaxNoProgressIdleTimes = 10; 122 GCIdleTimeHandler()123 GCIdleTimeHandler() : idle_times_which_made_no_progress_(0) {} 124 125 GCIdleTimeAction Compute(double idle_time_in_ms, 126 GCIdleTimeHeapState heap_state); 127 ResetNoProgressCounter()128 void ResetNoProgressCounter() { idle_times_which_made_no_progress_ = 0; } 129 130 static size_t EstimateMarkingStepSize(double idle_time_in_ms, 131 double marking_speed_in_bytes_per_ms); 132 133 static double EstimateFinalIncrementalMarkCompactTime( 134 size_t size_of_objects, double mark_compact_speed_in_bytes_per_ms); 135 136 static bool ShouldDoContextDisposalMarkCompact(int context_disposed, 137 double contexts_disposal_rate); 138 139 static bool ShouldDoFinalIncrementalMarkCompact( 140 double idle_time_in_ms, size_t size_of_objects, 141 double final_incremental_mark_compact_speed_in_bytes_per_ms); 142 143 static bool ShouldDoOverApproximateWeakClosure(double idle_time_in_ms); 144 145 private: 146 GCIdleTimeAction NothingOrDone(double idle_time_in_ms); 147 148 // Idle notifications with no progress. 149 int idle_times_which_made_no_progress_; 150 151 DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler); 152 }; 153 154 } // namespace internal 155 } // namespace v8 156 157 #endif // V8_HEAP_GC_IDLE_TIME_HANDLER_H_ 158