| 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 #include "src/heap/gc-tracer.h" | 6 #include "src/heap/gc-tracer.h" |
| 7 #include "src/utils.h" | 7 #include "src/utils.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 if (additional_work) { | 32 if (additional_work) { |
| 33 PrintF("; finalized marking"); | 33 PrintF("; finalized marking"); |
| 34 } | 34 } |
| 35 break; | 35 break; |
| 36 case DO_SCAVENGE: | 36 case DO_SCAVENGE: |
| 37 PrintF("scavenge"); | 37 PrintF("scavenge"); |
| 38 break; | 38 break; |
| 39 case DO_FULL_GC: | 39 case DO_FULL_GC: |
| 40 PrintF("full GC"); | 40 PrintF("full GC"); |
| 41 break; | 41 break; |
| 42 case DO_FULL_GC_COMPACT: | |
| 43 PrintF("full GC compact"); | |
| 44 break; | |
| 45 case DO_FINALIZE_SWEEPING: | 42 case DO_FINALIZE_SWEEPING: |
| 46 PrintF("finalize sweeping"); | 43 PrintF("finalize sweeping"); |
| 47 break; | 44 break; |
| 48 } | 45 } |
| 49 } | 46 } |
| 50 | 47 |
| 51 | 48 |
| 52 void GCIdleTimeHandler::HeapState::Print() { | 49 void GCIdleTimeHandler::HeapState::Print() { |
| 53 PrintF("contexts_disposed=%d ", contexts_disposed); | 50 PrintF("contexts_disposed=%d ", contexts_disposed); |
| 54 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate); | 51 PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 return true; | 149 return true; |
| 153 } | 150 } |
| 154 } | 151 } |
| 155 return false; | 152 return false; |
| 156 } | 153 } |
| 157 | 154 |
| 158 | 155 |
| 159 bool GCIdleTimeHandler::ShouldDoMarkCompact( | 156 bool GCIdleTimeHandler::ShouldDoMarkCompact( |
| 160 size_t idle_time_in_ms, size_t size_of_objects, | 157 size_t idle_time_in_ms, size_t size_of_objects, |
| 161 size_t mark_compact_speed_in_bytes_per_ms) { | 158 size_t mark_compact_speed_in_bytes_per_ms) { |
| 162 return idle_time_in_ms >= | 159 return idle_time_in_ms >= kMaxScheduledIdleTime && |
| 163 EstimateMarkCompactTime(size_of_objects, | 160 idle_time_in_ms >= |
| 164 mark_compact_speed_in_bytes_per_ms); | 161 EstimateMarkCompactTime(size_of_objects, |
| 162 mark_compact_speed_in_bytes_per_ms); |
| 165 } | 163 } |
| 166 | 164 |
| 167 | 165 |
| 168 bool GCIdleTimeHandler::ShouldDoReduceMemoryMarkCompact( | |
| 169 size_t idle_time_in_ms) { | |
| 170 return idle_time_in_ms >= kMinTimeForReduceMemory; | |
| 171 } | |
| 172 | |
| 173 | |
| 174 bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact( | 166 bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact( |
| 175 int contexts_disposed, double contexts_disposal_rate) { | 167 int contexts_disposed, double contexts_disposal_rate) { |
| 176 return contexts_disposed > 0 && contexts_disposal_rate > 0 && | 168 return contexts_disposed > 0 && contexts_disposal_rate > 0 && |
| 177 contexts_disposal_rate < kHighContextDisposalRate; | 169 contexts_disposal_rate < kHighContextDisposalRate; |
| 178 } | 170 } |
| 179 | 171 |
| 180 | 172 |
| 181 bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( | 173 bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( |
| 182 size_t idle_time_in_ms, size_t size_of_objects, | 174 size_t idle_time_in_ms, size_t size_of_objects, |
| 183 size_t final_incremental_mark_compact_speed_in_bytes_per_ms) { | 175 size_t final_incremental_mark_compact_speed_in_bytes_per_ms) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 208 | 200 |
| 209 // The following logic is implemented by the controller: | 201 // The following logic is implemented by the controller: |
| 210 // (1) If we don't have any idle time, do nothing, unless a context was | 202 // (1) If we don't have any idle time, do nothing, unless a context was |
| 211 // disposed, incremental marking is stopped, and the heap is small. Then do | 203 // disposed, incremental marking is stopped, and the heap is small. Then do |
| 212 // a full GC. | 204 // a full GC. |
| 213 // (2) If the new space is almost full and we can afford a Scavenge or if the | 205 // (2) If the new space is almost full and we can afford a Scavenge or if the |
| 214 // next Scavenge will very likely take long, then a Scavenge is performed. | 206 // next Scavenge will very likely take long, then a Scavenge is performed. |
| 215 // (3) If there is currently no MarkCompact idle round going on, we start a | 207 // (3) If there is currently no MarkCompact idle round going on, we start a |
| 216 // new idle round if enough garbage was created. Otherwise we do not perform | 208 // new idle round if enough garbage was created. Otherwise we do not perform |
| 217 // garbage collection to keep system utilization low. | 209 // garbage collection to keep system utilization low. |
| 218 // (4) If we have long idle time, we try to reduce the memory footprint. | 210 // (4) If incremental marking is done, we perform a full garbage collection |
| 219 // (5) If incremental marking is done, we perform a full garbage collection | 211 // if we are allowed to still do full garbage collections during this idle |
| 220 // if we are allowed to still do full garbage collections during this idle | |
| 221 // round or if we are not allowed to start incremental marking. Otherwise we | 212 // round or if we are not allowed to start incremental marking. Otherwise we |
| 222 // do not perform garbage collection to keep system utilization low. | 213 // do not perform garbage collection to keep system utilization low. |
| 223 // (6) If sweeping is in progress and we received a large enough idle time | 214 // (5) If sweeping is in progress and we received a large enough idle time |
| 224 // request, we finalize sweeping here. | 215 // request, we finalize sweeping here. |
| 225 // (7) If incremental marking is in progress, we perform a marking step. Note, | 216 // (6) If incremental marking is in progress, we perform a marking step. Note, |
| 226 // that this currently may trigger a full garbage collection. | 217 // that this currently may trigger a full garbage collection. |
| 227 GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms, | 218 GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms, |
| 228 HeapState heap_state) { | 219 HeapState heap_state) { |
| 229 if (static_cast<int>(idle_time_in_ms) <= 0) { | 220 if (static_cast<int>(idle_time_in_ms) <= 0) { |
| 230 if (heap_state.contexts_disposed > 0) { | 221 if (heap_state.contexts_disposed > 0) { |
| 231 StartIdleRound(); | 222 StartIdleRound(); |
| 232 } | 223 } |
| 233 if (heap_state.incremental_marking_stopped) { | 224 if (heap_state.incremental_marking_stopped) { |
| 234 if (ShouldDoContextDisposalMarkCompact( | 225 if (ShouldDoContextDisposalMarkCompact( |
| 235 heap_state.contexts_disposed, | 226 heap_state.contexts_disposed, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 249 } | 240 } |
| 250 | 241 |
| 251 if (IsMarkCompactIdleRoundFinished()) { | 242 if (IsMarkCompactIdleRoundFinished()) { |
| 252 if (EnoughGarbageSinceLastIdleRound()) { | 243 if (EnoughGarbageSinceLastIdleRound()) { |
| 253 StartIdleRound(); | 244 StartIdleRound(); |
| 254 } else { | 245 } else { |
| 255 return GCIdleTimeAction::Done(); | 246 return GCIdleTimeAction::Done(); |
| 256 } | 247 } |
| 257 } | 248 } |
| 258 | 249 |
| 259 if (ShouldDoReduceMemoryMarkCompact(static_cast<size_t>(idle_time_in_ms))) { | |
| 260 return GCIdleTimeAction::FullGCCompact(); | |
| 261 } | |
| 262 | |
| 263 if (heap_state.incremental_marking_stopped) { | 250 if (heap_state.incremental_marking_stopped) { |
| 264 if (ShouldDoMarkCompact(static_cast<size_t>(idle_time_in_ms), | 251 if (ShouldDoMarkCompact(static_cast<size_t>(idle_time_in_ms), |
| 265 heap_state.size_of_objects, | 252 heap_state.size_of_objects, |
| 266 heap_state.mark_compact_speed_in_bytes_per_ms)) { | 253 heap_state.mark_compact_speed_in_bytes_per_ms)) { |
| 267 return GCIdleTimeAction::FullGC(); | 254 return GCIdleTimeAction::FullGC(); |
| 268 } | 255 } |
| 269 } | 256 } |
| 270 if (heap_state.sweeping_in_progress) { | 257 if (heap_state.sweeping_in_progress) { |
| 271 if (heap_state.sweeping_completed) { | 258 if (heap_state.sweeping_completed) { |
| 272 return GCIdleTimeAction::FinalizeSweeping(); | 259 return GCIdleTimeAction::FinalizeSweeping(); |
| 273 } else { | 260 } else { |
| 274 return NothingOrDone(); | 261 return NothingOrDone(); |
| 275 } | 262 } |
| 276 } | 263 } |
| 277 if (heap_state.incremental_marking_stopped && | 264 if (heap_state.incremental_marking_stopped && |
| 278 !heap_state.can_start_incremental_marking) { | 265 !heap_state.can_start_incremental_marking) { |
| 279 return NothingOrDone(); | 266 return NothingOrDone(); |
| 280 } | 267 } |
| 281 | 268 |
| 282 size_t step_size = EstimateMarkingStepSize( | 269 size_t step_size = EstimateMarkingStepSize( |
| 283 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), | 270 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), |
| 284 heap_state.incremental_marking_speed_in_bytes_per_ms); | 271 heap_state.incremental_marking_speed_in_bytes_per_ms); |
| 285 return GCIdleTimeAction::IncrementalMarking(step_size); | 272 return GCIdleTimeAction::IncrementalMarking(step_size); |
| 286 } | 273 } |
| 287 } | 274 } |
| 288 } | 275 } |
| OLD | NEW |