| 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/heap/gc-tracer.h" | 7 #include "src/heap/gc-tracer.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 const char* GCTracer::Event::TypeName(bool short_name) const { | 62 const char* GCTracer::Event::TypeName(bool short_name) const { |
| 63 switch (type) { | 63 switch (type) { |
| 64 case SCAVENGER: | 64 case SCAVENGER: |
| 65 if (short_name) { | 65 if (short_name) { |
| 66 return "s"; | 66 return "s"; |
| 67 } else { | 67 } else { |
| 68 return "Scavenge"; | 68 return "Scavenge"; |
| 69 } | 69 } |
| 70 case MARK_COMPACTOR: | 70 case MARK_COMPACTOR: |
| 71 case INCREMENTAL_MARK_COMPACTOR: |
| 71 if (short_name) { | 72 if (short_name) { |
| 72 return "ms"; | 73 return "ms"; |
| 73 } else { | 74 } else { |
| 74 return "Mark-sweep"; | 75 return "Mark-sweep"; |
| 75 } | 76 } |
| 76 case START: | 77 case START: |
| 77 if (short_name) { | 78 if (short_name) { |
| 78 return "st"; | 79 return "st"; |
| 79 } else { | 80 } else { |
| 80 return "Start"; | 81 return "Start"; |
| 81 } | 82 } |
| 82 } | 83 } |
| 83 return "Unknown Event Type"; | 84 return "Unknown Event Type"; |
| 84 } | 85 } |
| 85 | 86 |
| 86 | 87 |
| 87 GCTracer::GCTracer(Heap* heap) | 88 GCTracer::GCTracer(Heap* heap) |
| 88 : heap_(heap), | 89 : heap_(heap), |
| 89 cumulative_incremental_marking_steps_(0), | 90 cumulative_incremental_marking_steps_(0), |
| 90 cumulative_incremental_marking_bytes_(0), | 91 cumulative_incremental_marking_bytes_(0), |
| 91 cumulative_incremental_marking_duration_(0.0), | 92 cumulative_incremental_marking_duration_(0.0), |
| 92 cumulative_pure_incremental_marking_duration_(0.0), | 93 cumulative_pure_incremental_marking_duration_(0.0), |
| 93 longest_incremental_marking_step_(0.0), | 94 longest_incremental_marking_step_(0.0), |
| 94 cumulative_marking_duration_(0.0), | 95 cumulative_marking_duration_(0.0), |
| 95 cumulative_sweeping_duration_(0.0), | 96 cumulative_sweeping_duration_(0.0), |
| 96 new_space_top_after_gc_(0), | 97 new_space_top_after_gc_(0), |
| 97 start_counter_(0) { | 98 start_counter_(0) { |
| 98 current_ = Event(Event::START, NULL, NULL); | 99 current_ = Event(Event::START, NULL, NULL); |
| 99 current_.end_time = base::OS::TimeCurrentMillis(); | 100 current_.end_time = base::OS::TimeCurrentMillis(); |
| 100 previous_ = previous_mark_compactor_event_ = current_; | 101 previous_ = previous_incremental_mark_compactor_event_ = current_; |
| 101 } | 102 } |
| 102 | 103 |
| 103 | 104 |
| 104 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, | 105 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, |
| 105 const char* collector_reason) { | 106 const char* collector_reason) { |
| 106 start_counter_++; | 107 start_counter_++; |
| 107 if (start_counter_ != 1) return; | 108 if (start_counter_ != 1) return; |
| 108 | 109 |
| 109 previous_ = current_; | 110 previous_ = current_; |
| 110 double start_time = base::OS::TimeCurrentMillis(); | 111 double start_time = base::OS::TimeCurrentMillis(); |
| 111 if (new_space_top_after_gc_ != 0) { | 112 if (new_space_top_after_gc_ != 0) { |
| 112 AddNewSpaceAllocationTime( | 113 AddNewSpaceAllocationTime( |
| 113 start_time - previous_.end_time, | 114 start_time - previous_.end_time, |
| 114 reinterpret_cast<intptr_t>((heap_->new_space()->top()) - | 115 reinterpret_cast<intptr_t>((heap_->new_space()->top()) - |
| 115 new_space_top_after_gc_)); | 116 new_space_top_after_gc_)); |
| 116 } | 117 } |
| 117 if (current_.type == Event::MARK_COMPACTOR) | 118 if (current_.type == Event::INCREMENTAL_MARK_COMPACTOR) |
| 118 previous_mark_compactor_event_ = current_; | 119 previous_incremental_mark_compactor_event_ = current_; |
| 119 | 120 |
| 120 if (collector == SCAVENGER) { | 121 if (collector == SCAVENGER) { |
| 121 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); | 122 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); |
| 122 } else { | 123 } else if (collector == MARK_COMPACTOR) { |
| 123 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); | 124 if (heap_->incremental_marking()->IsMarking()) { |
| 125 current_ = |
| 126 Event(Event::INCREMENTAL_MARK_COMPACTOR, gc_reason, collector_reason); |
| 127 } else { |
| 128 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); |
| 129 } |
| 124 } | 130 } |
| 125 | 131 |
| 126 current_.start_time = start_time; | 132 current_.start_time = start_time; |
| 127 current_.start_object_size = heap_->SizeOfObjects(); | 133 current_.start_object_size = heap_->SizeOfObjects(); |
| 128 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); | 134 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 129 current_.start_holes_size = CountTotalHolesSize(heap_); | 135 current_.start_holes_size = CountTotalHolesSize(heap_); |
| 130 current_.new_space_object_size = | 136 current_.new_space_object_size = |
| 131 heap_->new_space()->top() - heap_->new_space()->bottom(); | 137 heap_->new_space()->top() - heap_->new_space()->bottom(); |
| 132 | 138 |
| 133 current_.cumulative_incremental_marking_steps = | 139 current_.cumulative_incremental_marking_steps = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 151 if (start_counter_ != 0) { | 157 if (start_counter_ != 0) { |
| 152 if (FLAG_trace_gc) { | 158 if (FLAG_trace_gc) { |
| 153 PrintF("[Finished reentrant %s during %s.]\n", | 159 PrintF("[Finished reentrant %s during %s.]\n", |
| 154 collector == SCAVENGER ? "Scavenge" : "Mark-sweep", | 160 collector == SCAVENGER ? "Scavenge" : "Mark-sweep", |
| 155 current_.TypeName(false)); | 161 current_.TypeName(false)); |
| 156 } | 162 } |
| 157 return; | 163 return; |
| 158 } | 164 } |
| 159 | 165 |
| 160 DCHECK(start_counter_ >= 0); | 166 DCHECK(start_counter_ >= 0); |
| 161 DCHECK( | 167 DCHECK((collector == SCAVENGER && current_.type == Event::SCAVENGER) || |
| 162 (collector == SCAVENGER && current_.type == Event::SCAVENGER) || | 168 (collector == MARK_COMPACTOR && |
| 163 (collector == MARK_COMPACTOR && current_.type == Event::MARK_COMPACTOR)); | 169 (current_.type == Event::MARK_COMPACTOR || |
| 170 current_.type == Event::INCREMENTAL_MARK_COMPACTOR))); |
| 164 | 171 |
| 165 current_.end_time = base::OS::TimeCurrentMillis(); | 172 current_.end_time = base::OS::TimeCurrentMillis(); |
| 166 current_.end_object_size = heap_->SizeOfObjects(); | 173 current_.end_object_size = heap_->SizeOfObjects(); |
| 167 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); | 174 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 168 current_.end_holes_size = CountTotalHolesSize(heap_); | 175 current_.end_holes_size = CountTotalHolesSize(heap_); |
| 169 new_space_top_after_gc_ = | 176 new_space_top_after_gc_ = |
| 170 reinterpret_cast<intptr_t>(heap_->new_space()->top()); | 177 reinterpret_cast<intptr_t>(heap_->new_space()->top()); |
| 171 | 178 |
| 172 if (current_.type == Event::SCAVENGER) { | 179 if (current_.type == Event::SCAVENGER) { |
| 173 current_.incremental_marking_steps = | 180 current_.incremental_marking_steps = |
| 174 current_.cumulative_incremental_marking_steps - | 181 current_.cumulative_incremental_marking_steps - |
| 175 previous_.cumulative_incremental_marking_steps; | 182 previous_.cumulative_incremental_marking_steps; |
| 176 current_.incremental_marking_bytes = | 183 current_.incremental_marking_bytes = |
| 177 current_.cumulative_incremental_marking_bytes - | 184 current_.cumulative_incremental_marking_bytes - |
| 178 previous_.cumulative_incremental_marking_bytes; | 185 previous_.cumulative_incremental_marking_bytes; |
| 179 current_.incremental_marking_duration = | 186 current_.incremental_marking_duration = |
| 180 current_.cumulative_incremental_marking_duration - | 187 current_.cumulative_incremental_marking_duration - |
| 181 previous_.cumulative_incremental_marking_duration; | 188 previous_.cumulative_incremental_marking_duration; |
| 182 current_.pure_incremental_marking_duration = | 189 current_.pure_incremental_marking_duration = |
| 183 current_.cumulative_pure_incremental_marking_duration - | 190 current_.cumulative_pure_incremental_marking_duration - |
| 184 previous_.cumulative_pure_incremental_marking_duration; | 191 previous_.cumulative_pure_incremental_marking_duration; |
| 185 scavenger_events_.push_front(current_); | 192 scavenger_events_.push_front(current_); |
| 186 } else { | 193 } else if (current_.type == Event::INCREMENTAL_MARK_COMPACTOR) { |
| 187 current_.incremental_marking_steps = | 194 current_.incremental_marking_steps = |
| 188 current_.cumulative_incremental_marking_steps - | 195 current_.cumulative_incremental_marking_steps - |
| 189 previous_mark_compactor_event_.cumulative_incremental_marking_steps; | 196 previous_incremental_mark_compactor_event_ |
| 197 .cumulative_incremental_marking_steps; |
| 190 current_.incremental_marking_bytes = | 198 current_.incremental_marking_bytes = |
| 191 current_.cumulative_incremental_marking_bytes - | 199 current_.cumulative_incremental_marking_bytes - |
| 192 previous_mark_compactor_event_.cumulative_incremental_marking_bytes; | 200 previous_incremental_mark_compactor_event_ |
| 201 .cumulative_incremental_marking_bytes; |
| 193 current_.incremental_marking_duration = | 202 current_.incremental_marking_duration = |
| 194 current_.cumulative_incremental_marking_duration - | 203 current_.cumulative_incremental_marking_duration - |
| 195 previous_mark_compactor_event_.cumulative_incremental_marking_duration; | 204 previous_incremental_mark_compactor_event_ |
| 205 .cumulative_incremental_marking_duration; |
| 196 current_.pure_incremental_marking_duration = | 206 current_.pure_incremental_marking_duration = |
| 197 current_.cumulative_pure_incremental_marking_duration - | 207 current_.cumulative_pure_incremental_marking_duration - |
| 198 previous_mark_compactor_event_ | 208 previous_incremental_mark_compactor_event_ |
| 199 .cumulative_pure_incremental_marking_duration; | 209 .cumulative_pure_incremental_marking_duration; |
| 200 longest_incremental_marking_step_ = 0.0; | 210 longest_incremental_marking_step_ = 0.0; |
| 211 incremental_mark_compactor_events_.push_front(current_); |
| 212 } else { |
| 213 DCHECK(current_.incremental_marking_bytes == 0); |
| 214 DCHECK(current_.incremental_marking_duration == 0); |
| 215 DCHECK(current_.pure_incremental_marking_duration == 0); |
| 216 DCHECK(longest_incremental_marking_step_ == 0.0); |
| 201 mark_compactor_events_.push_front(current_); | 217 mark_compactor_events_.push_front(current_); |
| 202 } | 218 } |
| 203 | 219 |
| 204 // TODO(ernstm): move the code below out of GCTracer. | 220 // TODO(ernstm): move the code below out of GCTracer. |
| 205 | 221 |
| 206 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 222 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 207 | 223 |
| 208 double duration = current_.end_time - current_.start_time; | 224 double duration = current_.end_time - current_.start_time; |
| 209 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); | 225 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); |
| 210 | 226 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 409 |
| 394 return maximum; | 410 return maximum; |
| 395 } | 411 } |
| 396 | 412 |
| 397 | 413 |
| 398 double GCTracer::MeanIncrementalMarkingDuration() const { | 414 double GCTracer::MeanIncrementalMarkingDuration() const { |
| 399 if (cumulative_incremental_marking_steps_ == 0) return 0.0; | 415 if (cumulative_incremental_marking_steps_ == 0) return 0.0; |
| 400 | 416 |
| 401 // We haven't completed an entire round of incremental marking, yet. | 417 // We haven't completed an entire round of incremental marking, yet. |
| 402 // Use data from GCTracer instead of data from event buffers. | 418 // Use data from GCTracer instead of data from event buffers. |
| 403 if (mark_compactor_events_.empty()) { | 419 if (incremental_mark_compactor_events_.empty()) { |
| 404 return cumulative_incremental_marking_duration_ / | 420 return cumulative_incremental_marking_duration_ / |
| 405 cumulative_incremental_marking_steps_; | 421 cumulative_incremental_marking_steps_; |
| 406 } | 422 } |
| 407 | 423 |
| 408 int steps = 0; | 424 int steps = 0; |
| 409 double durations = 0.0; | 425 double durations = 0.0; |
| 410 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | 426 EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin(); |
| 411 while (iter != mark_compactor_events_.end()) { | 427 while (iter != incremental_mark_compactor_events_.end()) { |
| 412 steps += iter->incremental_marking_steps; | 428 steps += iter->incremental_marking_steps; |
| 413 durations += iter->incremental_marking_duration; | 429 durations += iter->incremental_marking_duration; |
| 414 ++iter; | 430 ++iter; |
| 415 } | 431 } |
| 416 | 432 |
| 417 if (steps == 0) return 0.0; | 433 if (steps == 0) return 0.0; |
| 418 | 434 |
| 419 return durations / steps; | 435 return durations / steps; |
| 420 } | 436 } |
| 421 | 437 |
| 422 | 438 |
| 423 double GCTracer::MaxIncrementalMarkingDuration() const { | 439 double GCTracer::MaxIncrementalMarkingDuration() const { |
| 424 // We haven't completed an entire round of incremental marking, yet. | 440 // We haven't completed an entire round of incremental marking, yet. |
| 425 // Use data from GCTracer instead of data from event buffers. | 441 // Use data from GCTracer instead of data from event buffers. |
| 426 if (mark_compactor_events_.empty()) return longest_incremental_marking_step_; | 442 if (incremental_mark_compactor_events_.empty()) |
| 443 return longest_incremental_marking_step_; |
| 427 | 444 |
| 428 double max_duration = 0.0; | 445 double max_duration = 0.0; |
| 429 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | 446 EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin(); |
| 430 while (iter != mark_compactor_events_.end()) | 447 while (iter != incremental_mark_compactor_events_.end()) |
| 431 max_duration = Max(iter->longest_incremental_marking_step, max_duration); | 448 max_duration = Max(iter->longest_incremental_marking_step, max_duration); |
| 432 | 449 |
| 433 return max_duration; | 450 return max_duration; |
| 434 } | 451 } |
| 435 | 452 |
| 436 | 453 |
| 437 intptr_t GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const { | 454 intptr_t GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const { |
| 438 if (cumulative_incremental_marking_duration_ == 0.0) return 0; | 455 if (cumulative_incremental_marking_duration_ == 0.0) return 0; |
| 439 | 456 |
| 440 // We haven't completed an entire round of incremental marking, yet. | 457 // We haven't completed an entire round of incremental marking, yet. |
| 441 // Use data from GCTracer instead of data from event buffers. | 458 // Use data from GCTracer instead of data from event buffers. |
| 442 if (mark_compactor_events_.empty()) { | 459 if (incremental_mark_compactor_events_.empty()) { |
| 443 return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ / | 460 return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ / |
| 444 cumulative_pure_incremental_marking_duration_); | 461 cumulative_pure_incremental_marking_duration_); |
| 445 } | 462 } |
| 446 | 463 |
| 447 intptr_t bytes = 0; | 464 intptr_t bytes = 0; |
| 448 double durations = 0.0; | 465 double durations = 0.0; |
| 449 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | 466 EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin(); |
| 450 while (iter != mark_compactor_events_.end()) { | 467 while (iter != incremental_mark_compactor_events_.end()) { |
| 451 bytes += iter->incremental_marking_bytes; | 468 bytes += iter->incremental_marking_bytes; |
| 452 durations += iter->pure_incremental_marking_duration; | 469 durations += iter->pure_incremental_marking_duration; |
| 453 ++iter; | 470 ++iter; |
| 454 } | 471 } |
| 455 | 472 |
| 456 if (durations == 0.0) return 0; | 473 if (durations == 0.0) return 0; |
| 457 | 474 |
| 458 return static_cast<intptr_t>(bytes / durations); | 475 return static_cast<intptr_t>(bytes / durations); |
| 459 } | 476 } |
| 460 | 477 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 474 return static_cast<intptr_t>(bytes / durations); | 491 return static_cast<intptr_t>(bytes / durations); |
| 475 } | 492 } |
| 476 | 493 |
| 477 | 494 |
| 478 intptr_t GCTracer::MarkCompactSpeedInBytesPerMillisecond() const { | 495 intptr_t GCTracer::MarkCompactSpeedInBytesPerMillisecond() const { |
| 479 intptr_t bytes = 0; | 496 intptr_t bytes = 0; |
| 480 double durations = 0.0; | 497 double durations = 0.0; |
| 481 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | 498 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
| 482 while (iter != mark_compactor_events_.end()) { | 499 while (iter != mark_compactor_events_.end()) { |
| 483 bytes += iter->start_object_size; | 500 bytes += iter->start_object_size; |
| 484 durations += iter->end_time - iter->start_time + | 501 durations += iter->end_time - iter->start_time; |
| 485 iter->pure_incremental_marking_duration; | |
| 486 ++iter; | 502 ++iter; |
| 487 } | 503 } |
| 488 | 504 |
| 505 if (durations == 0.0) return 0; |
| 506 |
| 507 return static_cast<intptr_t>(bytes / durations); |
| 508 } |
| 509 |
| 510 |
| 511 intptr_t GCTracer::FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() |
| 512 const { |
| 513 intptr_t bytes = 0; |
| 514 double durations = 0.0; |
| 515 EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin(); |
| 516 while (iter != incremental_mark_compactor_events_.end()) { |
| 517 bytes += iter->start_object_size; |
| 518 durations += iter->end_time - iter->start_time; |
| 519 ++iter; |
| 520 } |
| 521 |
| 489 if (durations == 0.0) return 0; | 522 if (durations == 0.0) return 0; |
| 490 | 523 |
| 491 return static_cast<intptr_t>(bytes / durations); | 524 return static_cast<intptr_t>(bytes / durations); |
| 492 } | 525 } |
| 493 | 526 |
| 494 | 527 |
| 495 intptr_t GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond() const { | 528 intptr_t GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond() const { |
| 496 intptr_t bytes = 0; | 529 intptr_t bytes = 0; |
| 497 double durations = 0.0; | 530 double durations = 0.0; |
| 498 AllocationEventBuffer::const_iterator iter = allocation_events_.begin(); | 531 AllocationEventBuffer::const_iterator iter = allocation_events_.begin(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 517 context_disposal_events_.begin(); | 550 context_disposal_events_.begin(); |
| 518 while (iter != context_disposal_events_.end()) { | 551 while (iter != context_disposal_events_.end()) { |
| 519 end = iter->time_; | 552 end = iter->time_; |
| 520 ++iter; | 553 ++iter; |
| 521 } | 554 } |
| 522 | 555 |
| 523 return (begin - end) / context_disposal_events_.size(); | 556 return (begin - end) / context_disposal_events_.size(); |
| 524 } | 557 } |
| 525 } | 558 } |
| 526 } // namespace v8::internal | 559 } // namespace v8::internal |
| OLD | NEW |