| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/gc-idle-time-handler.h" | 5 #include "src/heap/gc-idle-time-handler.h" |
| 6 | 6 |
| 7 #include "src/flags.h" | 7 #include "src/flags.h" |
| 8 #include "src/heap/gc-tracer.h" | 8 #include "src/heap/gc-tracer.h" |
| 9 #include "src/utils.h" | 9 #include "src/utils.h" |
| 10 | 10 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 break; | 25 break; |
| 26 case DO_NOTHING: | 26 case DO_NOTHING: |
| 27 PrintF("no action"); | 27 PrintF("no action"); |
| 28 break; | 28 break; |
| 29 case DO_INCREMENTAL_STEP: | 29 case DO_INCREMENTAL_STEP: |
| 30 PrintF("incremental step"); | 30 PrintF("incremental step"); |
| 31 if (additional_work) { | 31 if (additional_work) { |
| 32 PrintF("; finalized marking"); | 32 PrintF("; finalized marking"); |
| 33 } | 33 } |
| 34 break; | 34 break; |
| 35 case DO_SCAVENGE: | |
| 36 PrintF("scavenge"); | |
| 37 break; | |
| 38 case DO_FULL_GC: | 35 case DO_FULL_GC: |
| 39 PrintF("full GC"); | 36 PrintF("full GC"); |
| 40 break; | 37 break; |
| 41 } | 38 } |
| 42 } | 39 } |
| 43 | 40 |
| 44 | 41 |
| 45 void GCIdleTimeHeapState::Print() { | 42 void GCIdleTimeHeapState::Print() { |
| 46 PrintF("contexts_disposed=%d ", contexts_disposed); | 43 PrintF("contexts_disposed=%d ", contexts_disposed); |
| 47 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate); | 44 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate); |
| 48 PrintF("size_of_objects=%" V8_PTR_PREFIX "d ", size_of_objects); | 45 PrintF("size_of_objects=%" V8_PTR_PREFIX "d ", size_of_objects); |
| 49 PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped); | 46 PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped); |
| 50 PrintF("sweeping_in_progress=%d ", sweeping_in_progress); | 47 PrintF("sweeping_in_progress=%d ", sweeping_in_progress); |
| 51 PrintF("has_low_allocation_rate=%d", has_low_allocation_rate); | 48 PrintF("has_low_allocation_rate=%d", has_low_allocation_rate); |
| 52 PrintF("mark_compact_speed=%" V8_PTR_PREFIX "d ", | 49 PrintF("mark_compact_speed=%" V8_PTR_PREFIX "d ", |
| 53 mark_compact_speed_in_bytes_per_ms); | 50 mark_compact_speed_in_bytes_per_ms); |
| 54 PrintF("incremental_marking_speed=%" V8_PTR_PREFIX "d ", | 51 PrintF("incremental_marking_speed=%" V8_PTR_PREFIX "d ", |
| 55 incremental_marking_speed_in_bytes_per_ms); | 52 incremental_marking_speed_in_bytes_per_ms); |
| 56 PrintF("scavenge_speed=%" V8_PTR_PREFIX "d ", scavenge_speed_in_bytes_per_ms); | |
| 57 PrintF("new_space_size=%" V8_PTR_PREFIX "d ", used_new_space_size); | |
| 58 PrintF("new_space_capacity=%" V8_PTR_PREFIX "d ", new_space_capacity); | |
| 59 PrintF("new_space_allocation_throughput=%" V8_PTR_PREFIX "d ", | |
| 60 new_space_allocation_throughput_in_bytes_per_ms); | |
| 61 } | 53 } |
| 62 | 54 |
| 63 | 55 |
| 64 size_t GCIdleTimeHandler::EstimateMarkingStepSize( | 56 size_t GCIdleTimeHandler::EstimateMarkingStepSize( |
| 65 size_t idle_time_in_ms, size_t marking_speed_in_bytes_per_ms) { | 57 size_t idle_time_in_ms, size_t marking_speed_in_bytes_per_ms) { |
| 66 DCHECK(idle_time_in_ms > 0); | 58 DCHECK(idle_time_in_ms > 0); |
| 67 | 59 |
| 68 if (marking_speed_in_bytes_per_ms == 0) { | 60 if (marking_speed_in_bytes_per_ms == 0) { |
| 69 marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed; | 61 marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed; |
| 70 } | 62 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 100 if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) { | 92 if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) { |
| 101 final_incremental_mark_compact_speed_in_bytes_per_ms = | 93 final_incremental_mark_compact_speed_in_bytes_per_ms = |
| 102 kInitialConservativeFinalIncrementalMarkCompactSpeed; | 94 kInitialConservativeFinalIncrementalMarkCompactSpeed; |
| 103 } | 95 } |
| 104 size_t result = | 96 size_t result = |
| 105 size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms; | 97 size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms; |
| 106 return Min(result, kMaxFinalIncrementalMarkCompactTimeInMs); | 98 return Min(result, kMaxFinalIncrementalMarkCompactTimeInMs); |
| 107 } | 99 } |
| 108 | 100 |
| 109 | 101 |
| 110 bool GCIdleTimeHandler::ShouldDoScavenge( | |
| 111 size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size, | |
| 112 size_t scavenge_speed_in_bytes_per_ms, | |
| 113 size_t new_space_allocation_throughput_in_bytes_per_ms) { | |
| 114 if (idle_time_in_ms >= kMinBackgroundIdleTime) { | |
| 115 // It is better to do full GC for the background tab. | |
| 116 return false; | |
| 117 } | |
| 118 | |
| 119 // Calculates how much memory are we able to scavenge in | |
| 120 // kMaxFrameRenderingIdleTime ms. If scavenge_speed_in_bytes_per_ms is 0 we | |
| 121 // will take care of this later. | |
| 122 size_t idle_new_space_allocation_limit = | |
| 123 kMaxFrameRenderingIdleTime * scavenge_speed_in_bytes_per_ms; | |
| 124 | |
| 125 // If the limit is larger than the new space size, then scavenging used to be | |
| 126 // really fast. We can take advantage of the whole new space. | |
| 127 if (idle_new_space_allocation_limit > new_space_size) { | |
| 128 idle_new_space_allocation_limit = new_space_size; | |
| 129 } | |
| 130 | |
| 131 // We do not know the allocation throughput before the first scavenge. | |
| 132 // TODO(hpayer): Estimate allocation throughput before the first scavenge. | |
| 133 if (new_space_allocation_throughput_in_bytes_per_ms > 0) { | |
| 134 // We have to trigger scavenge before we reach the end of new space. | |
| 135 size_t adjust_limit = new_space_allocation_throughput_in_bytes_per_ms * | |
| 136 kTimeUntilNextIdleEvent; | |
| 137 if (adjust_limit > idle_new_space_allocation_limit) { | |
| 138 idle_new_space_allocation_limit = 0; | |
| 139 } else { | |
| 140 idle_new_space_allocation_limit -= adjust_limit; | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 // The allocated new space limit to trigger a scavange has to be at least | |
| 145 // kMinimumNewSpaceSizeToPerformScavenge. | |
| 146 if (idle_new_space_allocation_limit < kMinimumNewSpaceSizeToPerformScavenge) { | |
| 147 idle_new_space_allocation_limit = kMinimumNewSpaceSizeToPerformScavenge; | |
| 148 } | |
| 149 | |
| 150 // Set an initial scavenge speed if it is unknown. | |
| 151 if (scavenge_speed_in_bytes_per_ms == 0) { | |
| 152 scavenge_speed_in_bytes_per_ms = kInitialConservativeScavengeSpeed; | |
| 153 } | |
| 154 | |
| 155 // We apply a max factor to the new space size to make sure that a slowly | |
| 156 // allocating application still leaves enough of wiggle room to schedule a | |
| 157 // scavenge. | |
| 158 size_t max_limit; | |
| 159 const double kMaxNewSpaceSizeFactorLongIdleTimes = 0.5; | |
| 160 const double kMaxNewSpaceSizeFactorShortIdleTimes = 0.8; | |
| 161 if (idle_time_in_ms > kMaxFrameRenderingIdleTime) { | |
| 162 max_limit = static_cast<size_t>(new_space_size * | |
| 163 kMaxNewSpaceSizeFactorLongIdleTimes); | |
| 164 } else { | |
| 165 max_limit = static_cast<size_t>(new_space_size * | |
| 166 kMaxNewSpaceSizeFactorShortIdleTimes); | |
| 167 } | |
| 168 idle_new_space_allocation_limit = | |
| 169 Min(idle_new_space_allocation_limit, max_limit); | |
| 170 | |
| 171 // We perform a scavenge if we are over the idle new space limit and | |
| 172 // a scavenge fits into the given idle time bucket. | |
| 173 if (idle_new_space_allocation_limit <= used_new_space_size) { | |
| 174 if (used_new_space_size / scavenge_speed_in_bytes_per_ms <= | |
| 175 idle_time_in_ms) { | |
| 176 return true; | |
| 177 } | |
| 178 } | |
| 179 return false; | |
| 180 } | |
| 181 | |
| 182 | |
| 183 bool GCIdleTimeHandler::ShouldDoMarkCompact( | 102 bool GCIdleTimeHandler::ShouldDoMarkCompact( |
| 184 size_t idle_time_in_ms, size_t size_of_objects, | 103 size_t idle_time_in_ms, size_t size_of_objects, |
| 185 size_t mark_compact_speed_in_bytes_per_ms) { | 104 size_t mark_compact_speed_in_bytes_per_ms) { |
| 186 return idle_time_in_ms >= kMaxScheduledIdleTime && | 105 return idle_time_in_ms >= kMaxScheduledIdleTime && |
| 187 idle_time_in_ms >= | 106 idle_time_in_ms >= |
| 188 EstimateMarkCompactTime(size_of_objects, | 107 EstimateMarkCompactTime(size_of_objects, |
| 189 mark_compact_speed_in_bytes_per_ms); | 108 mark_compact_speed_in_bytes_per_ms); |
| 190 } | 109 } |
| 191 | 110 |
| 192 | 111 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 return GCIdleTimeAction::Nothing(); | 171 return GCIdleTimeAction::Nothing(); |
| 253 } | 172 } |
| 254 | 173 |
| 255 // We are in a context disposal GC scenario. Don't do anything if we do not | 174 // We are in a context disposal GC scenario. Don't do anything if we do not |
| 256 // get the right idle signal. | 175 // get the right idle signal. |
| 257 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed, | 176 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed, |
| 258 heap_state.contexts_disposal_rate)) { | 177 heap_state.contexts_disposal_rate)) { |
| 259 return NothingOrDone(idle_time_in_ms); | 178 return NothingOrDone(idle_time_in_ms); |
| 260 } | 179 } |
| 261 | 180 |
| 262 if (ShouldDoScavenge( | |
| 263 static_cast<size_t>(idle_time_in_ms), heap_state.new_space_capacity, | |
| 264 heap_state.used_new_space_size, | |
| 265 heap_state.scavenge_speed_in_bytes_per_ms, | |
| 266 heap_state.new_space_allocation_throughput_in_bytes_per_ms)) { | |
| 267 return GCIdleTimeAction::Scavenge(); | |
| 268 } | |
| 269 | |
| 270 if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) { | 181 if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) { |
| 271 return GCIdleTimeAction::Done(); | 182 return GCIdleTimeAction::Done(); |
| 272 } | 183 } |
| 273 | 184 |
| 274 return GCIdleTimeAction::IncrementalStep(); | 185 return GCIdleTimeAction::IncrementalStep(); |
| 275 } | 186 } |
| 276 | 187 |
| 277 | 188 |
| 278 } | 189 } |
| 279 } | 190 } |
| OLD | NEW |