Chromium Code Reviews| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/gc-tracer.h" | 7 #include "src/gc-tracer.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 gc_reason(gc_reason), | 25 gc_reason(gc_reason), |
| 26 collector_reason(collector_reason), | 26 collector_reason(collector_reason), |
| 27 start_time(0.0), | 27 start_time(0.0), |
| 28 end_time(0.0), | 28 end_time(0.0), |
| 29 start_object_size(0), | 29 start_object_size(0), |
| 30 end_object_size(0), | 30 end_object_size(0), |
| 31 start_memory_size(0), | 31 start_memory_size(0), |
| 32 end_memory_size(0), | 32 end_memory_size(0), |
| 33 start_holes_size(0), | 33 start_holes_size(0), |
| 34 end_holes_size(0), | 34 end_holes_size(0), |
| 35 cumulative_incremental_marking_steps(0), | |
| 35 incremental_marking_steps(0), | 36 incremental_marking_steps(0), |
| 36 incremental_marking_duration(0.0) { | 37 cumulative_incremental_marking_bytes(0), |
| 38 incremental_marking_bytes(0), | |
| 39 cumulative_incremental_marking_duration(0.0), | |
| 40 incremental_marking_duration(0.0), | |
| 41 longest_incremental_marking_step(0.0) { | |
| 37 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | 42 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
| 38 scopes[i] = 0; | 43 scopes[i] = 0; |
| 39 } | 44 } |
| 40 } | 45 } |
| 41 | 46 |
| 42 | 47 |
| 43 const char* GCTracer::Event::TypeName(bool short_name) const { | 48 const char* GCTracer::Event::TypeName(bool short_name) const { |
| 44 switch (type) { | 49 switch (type) { |
| 45 case SCAVENGER: | 50 case SCAVENGER: |
| 46 if (short_name) { | 51 if (short_name) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 60 } else { | 65 } else { |
| 61 return "Start"; | 66 return "Start"; |
| 62 } | 67 } |
| 63 } | 68 } |
| 64 return "Unknown Event Type"; | 69 return "Unknown Event Type"; |
| 65 } | 70 } |
| 66 | 71 |
| 67 | 72 |
| 68 GCTracer::GCTracer(Heap* heap) | 73 GCTracer::GCTracer(Heap* heap) |
| 69 : heap_(heap), | 74 : heap_(heap), |
| 70 incremental_marking_steps_(0), | 75 cumulative_incremental_marking_steps_(0), |
| 71 incremental_marking_duration_(0.0), | 76 cumulative_incremental_marking_bytes_(0), |
| 77 cumulative_incremental_marking_duration_(0.0), | |
| 72 longest_incremental_marking_step_(0.0) { | 78 longest_incremental_marking_step_(0.0) { |
| 73 current_ = Event(Event::START, NULL, NULL); | 79 current_ = Event(Event::START, NULL, NULL); |
| 74 current_.end_time = base::OS::TimeCurrentMillis(); | 80 current_.end_time = base::OS::TimeCurrentMillis(); |
| 75 previous_ = previous_mark_compactor_event_ = current_; | 81 previous_ = previous_mark_compactor_event_ = current_; |
| 76 } | 82 } |
| 77 | 83 |
| 78 | 84 |
| 79 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, | 85 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, |
| 80 const char* collector_reason) { | 86 const char* collector_reason) { |
| 81 previous_ = current_; | 87 previous_ = current_; |
| 82 if (current_.type == Event::MARK_COMPACTOR) | 88 if (current_.type == Event::MARK_COMPACTOR) |
| 83 previous_mark_compactor_event_ = current_; | 89 previous_mark_compactor_event_ = current_; |
| 84 | 90 |
| 85 if (collector == SCAVENGER) { | 91 if (collector == SCAVENGER) { |
| 86 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); | 92 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); |
| 87 } else { | 93 } else { |
| 88 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); | 94 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); |
| 89 } | 95 } |
| 90 | 96 |
| 91 current_.start_time = base::OS::TimeCurrentMillis(); | 97 current_.start_time = base::OS::TimeCurrentMillis(); |
| 92 current_.start_object_size = heap_->SizeOfObjects(); | 98 current_.start_object_size = heap_->SizeOfObjects(); |
| 93 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); | 99 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 94 current_.start_holes_size = CountTotalHolesSize(heap_); | 100 current_.start_holes_size = CountTotalHolesSize(heap_); |
| 95 | 101 |
| 96 current_.incremental_marking_steps = incremental_marking_steps_; | 102 current_.cumulative_incremental_marking_steps = |
| 97 current_.incremental_marking_duration = incremental_marking_duration_; | 103 cumulative_incremental_marking_steps_; |
| 104 current_.cumulative_incremental_marking_bytes = | |
| 105 cumulative_incremental_marking_bytes_; | |
| 106 current_.cumulative_incremental_marking_duration = | |
| 107 cumulative_incremental_marking_duration_; | |
| 98 current_.longest_incremental_marking_step = longest_incremental_marking_step_; | 108 current_.longest_incremental_marking_step = longest_incremental_marking_step_; |
| 99 | 109 |
| 100 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | 110 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
| 101 current_.scopes[i] = 0; | 111 current_.scopes[i] = 0; |
| 102 } | 112 } |
| 103 } | 113 } |
| 104 | 114 |
| 105 | 115 |
| 106 void GCTracer::Stop() { | 116 void GCTracer::Stop() { |
| 107 current_.end_time = base::OS::TimeCurrentMillis(); | 117 current_.end_time = base::OS::TimeCurrentMillis(); |
| 108 current_.end_object_size = heap_->SizeOfObjects(); | 118 current_.end_object_size = heap_->SizeOfObjects(); |
| 109 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); | 119 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 110 current_.end_holes_size = CountTotalHolesSize(heap_); | 120 current_.end_holes_size = CountTotalHolesSize(heap_); |
| 111 | 121 |
| 112 if (current_.type == Event::SCAVENGER) { | 122 if (current_.type == Event::SCAVENGER) { |
| 113 scavenger_events_.push_front(current_); | 123 scavenger_events_.push_front(current_); |
| 124 current_.incremental_marking_steps = | |
| 125 current_.cumulative_incremental_marking_steps - | |
| 126 previous_.cumulative_incremental_marking_steps; | |
| 127 current_.incremental_marking_bytes = | |
| 128 current_.cumulative_incremental_marking_bytes - | |
| 129 previous_.cumulative_incremental_marking_bytes; | |
| 130 current_.incremental_marking_duration = | |
| 131 current_.cumulative_incremental_marking_duration - | |
| 132 previous_.cumulative_incremental_marking_duration; | |
| 114 } else { | 133 } else { |
| 115 mark_compactor_events_.push_front(current_); | 134 mark_compactor_events_.push_front(current_); |
| 135 current_.incremental_marking_steps = | |
| 136 current_.cumulative_incremental_marking_steps - | |
| 137 previous_mark_compactor_event_.cumulative_incremental_marking_steps; | |
| 138 current_.incremental_marking_bytes = | |
| 139 current_.cumulative_incremental_marking_bytes - | |
| 140 previous_mark_compactor_event_.cumulative_incremental_marking_bytes; | |
| 141 current_.incremental_marking_duration = | |
| 142 current_.cumulative_incremental_marking_duration - | |
| 143 previous_mark_compactor_event_.cumulative_incremental_marking_duration; | |
| 144 longest_incremental_marking_step_ = 0.0; | |
| 116 } | 145 } |
| 117 | 146 |
| 118 if (current_.type == Event::MARK_COMPACTOR) | |
| 119 longest_incremental_marking_step_ = 0.0; | |
| 120 | |
| 121 // TODO(ernstm): move the code below out of GCTracer. | 147 // TODO(ernstm): move the code below out of GCTracer. |
| 122 | 148 |
| 123 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 149 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 124 | 150 |
| 125 double duration = current_.end_time - current_.start_time; | 151 double duration = current_.end_time - current_.start_time; |
| 126 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); | 152 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); |
| 127 | 153 |
| 128 heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator, | 154 heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator, |
| 129 current_.scopes[Scope::MC_MARK]); | 155 current_.scopes[Scope::MC_MARK]); |
| 130 | 156 |
| 131 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) | 157 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) |
| 132 return; | 158 return; |
| 133 | 159 |
| 134 if (FLAG_trace_gc) { | 160 if (FLAG_trace_gc) { |
| 135 if (FLAG_trace_gc_nvp) | 161 if (FLAG_trace_gc_nvp) |
| 136 PrintNVP(); | 162 PrintNVP(); |
| 137 else | 163 else |
| 138 Print(); | 164 Print(); |
| 139 | 165 |
| 140 heap_->PrintShortHeapStatistics(); | 166 heap_->PrintShortHeapStatistics(); |
| 141 } | 167 } |
| 142 } | 168 } |
| 143 | 169 |
| 144 | 170 |
| 145 void GCTracer::AddIncrementalMarkingStep(double duration) { | 171 void GCTracer::AddIncrementalMarkingStep(double duration, intptr_t bytes) { |
| 146 incremental_marking_steps_++; | 172 cumulative_incremental_marking_steps_++; |
| 147 incremental_marking_duration_ += duration; | 173 cumulative_incremental_marking_bytes_ += bytes; |
| 174 cumulative_incremental_marking_duration_ += duration; | |
| 148 longest_incremental_marking_step_ = | 175 longest_incremental_marking_step_ = |
| 149 Max(longest_incremental_marking_step_, duration); | 176 Max(longest_incremental_marking_step_, duration); |
| 150 } | 177 } |
| 151 | 178 |
| 152 | 179 |
| 153 void GCTracer::Print() const { | 180 void GCTracer::Print() const { |
| 154 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); | 181 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); |
| 155 | 182 |
| 156 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false), | 183 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false), |
| 157 static_cast<double>(current_.start_object_size) / MB, | 184 static_cast<double>(current_.start_object_size) / MB, |
| 158 static_cast<double>(current_.start_memory_size) / MB, | 185 static_cast<double>(current_.start_memory_size) / MB, |
| 159 static_cast<double>(current_.end_object_size) / MB, | 186 static_cast<double>(current_.end_object_size) / MB, |
| 160 static_cast<double>(current_.end_memory_size) / MB); | 187 static_cast<double>(current_.end_memory_size) / MB); |
| 161 | 188 |
| 162 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); | 189 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); |
| 163 if (external_time > 0) PrintF("%d / ", external_time); | 190 if (external_time > 0) PrintF("%d / ", external_time); |
| 164 | 191 |
| 165 double duration = current_.end_time - current_.start_time; | 192 double duration = current_.end_time - current_.start_time; |
| 166 PrintF("%.1f ms", duration); | 193 PrintF("%.1f ms", duration); |
| 167 if (current_.type == Event::SCAVENGER) { | 194 if (current_.type == Event::SCAVENGER) { |
| 168 int steps = current_.incremental_marking_steps - | 195 if (current_.incremental_marking_steps > 0) { |
| 169 previous_.incremental_marking_steps; | |
| 170 if (steps > 0) { | |
| 171 PrintF(" (+ %.1f ms in %d steps since last GC)", | 196 PrintF(" (+ %.1f ms in %d steps since last GC)", |
| 172 current_.incremental_marking_duration - | 197 current_.incremental_marking_duration, |
| 173 previous_.incremental_marking_duration, | 198 current_.incremental_marking_steps); |
| 174 steps); | |
| 175 } | 199 } |
| 176 } else { | 200 } else { |
| 177 int steps = current_.incremental_marking_steps - | 201 if (current_.incremental_marking_steps > 0) { |
| 178 previous_mark_compactor_event_.incremental_marking_steps; | |
| 179 if (steps > 0) { | |
| 180 PrintF( | 202 PrintF( |
| 181 " (+ %.1f ms in %d steps since start of marking, " | 203 " (+ %.1f ms in %d steps since start of marking, " |
| 182 "biggest step %.1f ms)", | 204 "biggest step %.1f ms)", |
| 183 current_.incremental_marking_duration - | 205 current_.incremental_marking_duration, |
| 184 previous_mark_compactor_event_.incremental_marking_duration, | 206 current_.incremental_marking_steps, |
| 185 steps, current_.longest_incremental_marking_step); | 207 current_.longest_incremental_marking_step); |
| 186 } | 208 } |
| 187 } | 209 } |
| 188 | 210 |
| 189 if (current_.gc_reason != NULL) { | 211 if (current_.gc_reason != NULL) { |
| 190 PrintF(" [%s]", current_.gc_reason); | 212 PrintF(" [%s]", current_.gc_reason); |
| 191 } | 213 } |
| 192 | 214 |
| 193 if (current_.collector_reason != NULL) { | 215 if (current_.collector_reason != NULL) { |
| 194 PrintF(" [%s]", current_.collector_reason); | 216 PrintF(" [%s]", current_.collector_reason); |
| 195 } | 217 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); | 267 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); |
| 246 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", | 268 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", |
| 247 heap_->semi_space_copied_object_size_); | 269 heap_->semi_space_copied_object_size_); |
| 248 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); | 270 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); |
| 249 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); | 271 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); |
| 250 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); | 272 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); |
| 251 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); | 273 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); |
| 252 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); | 274 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); |
| 253 | 275 |
| 254 if (current_.type == Event::SCAVENGER) { | 276 if (current_.type == Event::SCAVENGER) { |
| 255 PrintF("stepscount=%d ", current_.incremental_marking_steps - | 277 PrintF("stepscount=%d ", current_.incremental_marking_steps); |
|
Hannes Payer (out of office)
2014/07/28 13:04:12
Since you are here, can we make the names here uni
ernstm
2014/07/28 14:43:26
Done.
| |
| 256 previous_.incremental_marking_steps); | 278 PrintF("stepstook=%.1f ", current_.incremental_marking_duration); |
| 257 PrintF("stepstook=%.1f ", current_.incremental_marking_duration - | |
| 258 previous_.incremental_marking_duration); | |
| 259 } else { | 279 } else { |
| 260 PrintF("stepscount=%d ", | 280 PrintF("stepscount=%d ", current_.incremental_marking_steps); |
| 261 current_.incremental_marking_steps - | 281 PrintF("stepstook=%.1f ", current_.incremental_marking_duration); |
| 262 previous_mark_compactor_event_.incremental_marking_steps); | |
| 263 PrintF("stepstook=%.1f ", | |
| 264 current_.incremental_marking_duration - | |
| 265 previous_mark_compactor_event_.incremental_marking_duration); | |
| 266 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); | 282 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); |
|
Hannes Payer (out of office)
2014/07/28 13:04:12
Let's print the MarkingSpeedInBytesPerMillisecond
ernstm
2014/07/28 14:43:26
Done.
| |
| 267 } | 283 } |
| 268 | 284 |
| 269 PrintF("\n"); | 285 PrintF("\n"); |
| 270 } | 286 } |
| 271 | 287 |
| 272 | 288 |
| 273 double GCTracer::MeanDuration(const EventBuffer& events) const { | 289 double GCTracer::MeanDuration(const EventBuffer& events) const { |
| 274 if (events.empty()) return 0.0; | 290 if (events.empty()) return 0.0; |
| 275 | 291 |
| 276 double mean = 0.0; | 292 double mean = 0.0; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 292 while (iter != events.end()) { | 308 while (iter != events.end()) { |
| 293 maximum = Max(iter->end_time - iter->start_time, maximum); | 309 maximum = Max(iter->end_time - iter->start_time, maximum); |
| 294 ++iter; | 310 ++iter; |
| 295 } | 311 } |
| 296 | 312 |
| 297 return maximum; | 313 return maximum; |
| 298 } | 314 } |
| 299 | 315 |
| 300 | 316 |
| 301 double GCTracer::MeanIncrementalMarkingDuration() const { | 317 double GCTracer::MeanIncrementalMarkingDuration() const { |
| 302 if (mark_compactor_events_.empty()) return 0.0; | 318 if (cumulative_incremental_marking_steps_ == 0) return 0.0; |
| 303 | 319 |
| 304 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 320 // We haven't complete an entire round of incremental marking, yet. |
|
Hannes Payer (out of office)
2014/07/28 13:04:12
completed
ernstm
2014/07/28 14:43:26
Done.
| |
| 305 return last_mc->incremental_marking_duration / | 321 // Use data from GCTracer instead of data from event buffers. |
| 306 last_mc->incremental_marking_steps; | 322 if (mark_compactor_events_.empty()) { |
| 323 return cumulative_incremental_marking_duration_ / | |
| 324 cumulative_incremental_marking_steps_; | |
| 325 } | |
| 326 | |
| 327 int steps = 0; | |
| 328 double durations = 0.0; | |
| 329 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | |
| 330 while (iter != mark_compactor_events_.end()) { | |
| 331 steps += iter->incremental_marking_steps; | |
| 332 durations += iter->incremental_marking_duration; | |
| 333 ++iter; | |
| 334 } | |
| 335 | |
| 336 if (steps == 0) return 0.0; | |
| 337 | |
| 338 return durations / steps; | |
| 307 } | 339 } |
| 308 | 340 |
| 309 | 341 |
| 310 double GCTracer::MaxIncrementalMarkingDuration() const { | 342 double GCTracer::MaxIncrementalMarkingDuration() const { |
| 311 if (mark_compactor_events_.empty()) return 0.0; | 343 // We haven't complete an entire round of incremental marking, yet. |
|
Hannes Payer (out of office)
2014/07/28 13:04:13
completed
ernstm
2014/07/28 14:43:26
Done.
| |
| 344 // Use data from GCTracer instead of data from event buffers. | |
| 345 if (mark_compactor_events_.empty()) return longest_incremental_marking_step_; | |
| 312 | 346 |
| 313 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 347 double max_duration = 0.0; |
| 314 return last_mc->longest_incremental_marking_step; | 348 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
| 349 while (iter != mark_compactor_events_.end()) | |
| 350 max_duration = Max(iter->longest_incremental_marking_step, max_duration); | |
| 351 | |
| 352 return max_duration; | |
| 353 } | |
| 354 | |
| 355 | |
| 356 double GCTracer::MarkingSpeedInBytesPerMillisecond() const { | |
| 357 if (cumulative_incremental_marking_duration_ == 0.0) return 0.0; | |
| 358 | |
| 359 // We haven't complete an entire round of incremental marking, yet. | |
| 360 // Use data from GCTracer instead of data from event buffers. | |
| 361 if (mark_compactor_events_.empty()) { | |
| 362 return cumulative_incremental_marking_bytes_ / | |
| 363 cumulative_incremental_marking_duration_; | |
| 364 } | |
| 365 | |
| 366 intptr_t bytes = 0; | |
| 367 double durations = 0.0; | |
| 368 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | |
| 369 while (iter != mark_compactor_events_.end()) { | |
| 370 bytes += iter->incremental_marking_bytes; | |
| 371 durations += iter->incremental_marking_duration; | |
| 372 ++iter; | |
| 373 } | |
| 374 | |
| 375 if (durations == 0.0) return 0.0; | |
| 376 | |
| 377 return bytes / durations; | |
| 315 } | 378 } |
| 316 } | 379 } |
| 317 } // namespace v8::internal | 380 } // namespace v8::internal |
| OLD | NEW |