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-tracer.h" | 5 #include "src/heap/gc-tracer.h" |
6 | 6 |
7 #include "src/counters.h" | 7 #include "src/counters.h" |
8 #include "src/heap/heap-inl.h" | 8 #include "src/heap/heap-inl.h" |
9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
10 | 10 |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 "weak=%.2f " | 460 "weak=%.2f " |
461 "roots=%.2f " | 461 "roots=%.2f " |
462 "code=%.2f " | 462 "code=%.2f " |
463 "semispace=%.2f " | 463 "semispace=%.2f " |
464 "object_groups=%.2f " | 464 "object_groups=%.2f " |
465 "external_prologue=%.2f " | 465 "external_prologue=%.2f " |
466 "external_epilogue=%.2f " | 466 "external_epilogue=%.2f " |
467 "external_weak_global_handles=%.2f " | 467 "external_weak_global_handles=%.2f " |
468 "steps_count=%d " | 468 "steps_count=%d " |
469 "steps_took=%.1f " | 469 "steps_took=%.1f " |
470 "scavenge_throughput=%" V8_PTR_PREFIX | 470 "scavenge_throughput=%.f " |
471 "d " | |
472 "total_size_before=%" V8_PTR_PREFIX | 471 "total_size_before=%" V8_PTR_PREFIX |
473 "d " | 472 "d " |
474 "total_size_after=%" V8_PTR_PREFIX | 473 "total_size_after=%" V8_PTR_PREFIX |
475 "d " | 474 "d " |
476 "holes_size_before=%" V8_PTR_PREFIX | 475 "holes_size_before=%" V8_PTR_PREFIX |
477 "d " | 476 "d " |
478 "holes_size_after=%" V8_PTR_PREFIX | 477 "holes_size_after=%" V8_PTR_PREFIX |
479 "d " | 478 "d " |
480 "allocated=%" V8_PTR_PREFIX | 479 "allocated=%" V8_PTR_PREFIX |
481 "d " | 480 "d " |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 "sweep.code=%.1f " | 562 "sweep.code=%.1f " |
564 "sweep.map=%.1f " | 563 "sweep.map=%.1f " |
565 "sweep.old=%.1f " | 564 "sweep.old=%.1f " |
566 "incremental_finalize=%.1f " | 565 "incremental_finalize=%.1f " |
567 "steps_count=%d " | 566 "steps_count=%d " |
568 "steps_took=%.1f " | 567 "steps_took=%.1f " |
569 "longest_step=%.1f " | 568 "longest_step=%.1f " |
570 "finalization_steps_count=%d " | 569 "finalization_steps_count=%d " |
571 "finalization_steps_took=%.1f " | 570 "finalization_steps_took=%.1f " |
572 "finalization_longest_step=%.1f " | 571 "finalization_longest_step=%.1f " |
573 "incremental_marking_throughput=%" V8_PTR_PREFIX | 572 "incremental_marking_throughput=%.f " |
574 "d " | |
575 "total_size_before=%" V8_PTR_PREFIX | 573 "total_size_before=%" V8_PTR_PREFIX |
576 "d " | 574 "d " |
577 "total_size_after=%" V8_PTR_PREFIX | 575 "total_size_after=%" V8_PTR_PREFIX |
578 "d " | 576 "d " |
579 "holes_size_before=%" V8_PTR_PREFIX | 577 "holes_size_before=%" V8_PTR_PREFIX |
580 "d " | 578 "d " |
581 "holes_size_after=%" V8_PTR_PREFIX | 579 "holes_size_after=%" V8_PTR_PREFIX |
582 "d " | 580 "d " |
583 "allocated=%" V8_PTR_PREFIX | 581 "allocated=%" V8_PTR_PREFIX |
584 "d " | 582 "d " |
585 "promoted=%" V8_PTR_PREFIX | 583 "promoted=%" V8_PTR_PREFIX |
586 "d " | 584 "d " |
587 "semi_space_copied=%" V8_PTR_PREFIX | 585 "semi_space_copied=%" V8_PTR_PREFIX |
588 "d " | 586 "d " |
589 "nodes_died_in_new=%d " | 587 "nodes_died_in_new=%d " |
590 "nodes_copied_in_new=%d " | 588 "nodes_copied_in_new=%d " |
591 "nodes_promoted=%d " | 589 "nodes_promoted=%d " |
592 "promotion_ratio=%.1f%% " | 590 "promotion_ratio=%.1f%% " |
593 "average_survival_ratio=%.1f%% " | 591 "average_survival_ratio=%.1f%% " |
594 "promotion_rate=%.1f%% " | 592 "promotion_rate=%.1f%% " |
595 "semi_space_copy_rate=%.1f%% " | 593 "semi_space_copy_rate=%.1f%% " |
596 "new_space_allocation_throughput=%.1f " | 594 "new_space_allocation_throughput=%.1f " |
597 "context_disposal_rate=%.1f " | 595 "context_disposal_rate=%.1f " |
598 "compaction_speed=%" V8_PTR_PREFIX "d\n", | 596 "compaction_speed=%.f\n", |
599 heap_->isolate()->time_millis_since_init(), duration, | 597 heap_->isolate()->time_millis_since_init(), duration, |
600 spent_in_mutator, current_.TypeName(true), current_.reduce_memory, | 598 spent_in_mutator, current_.TypeName(true), current_.reduce_memory, |
601 current_.scopes[Scope::MC_CLEAR], | 599 current_.scopes[Scope::MC_CLEAR], |
602 current_.scopes[Scope::MC_CLEAR_CODE_FLUSH], | 600 current_.scopes[Scope::MC_CLEAR_CODE_FLUSH], |
603 current_.scopes[Scope::MC_CLEAR_DEPENDENT_CODE], | 601 current_.scopes[Scope::MC_CLEAR_DEPENDENT_CODE], |
604 current_.scopes[Scope::MC_CLEAR_GLOBAL_HANDLES], | 602 current_.scopes[Scope::MC_CLEAR_GLOBAL_HANDLES], |
605 current_.scopes[Scope::MC_CLEAR_MAPS], | 603 current_.scopes[Scope::MC_CLEAR_MAPS], |
606 current_.scopes[Scope::MC_CLEAR_SLOTS_BUFFER], | 604 current_.scopes[Scope::MC_CLEAR_SLOTS_BUFFER], |
607 current_.scopes[Scope::MC_CLEAR_STORE_BUFFER], | 605 current_.scopes[Scope::MC_CLEAR_STORE_BUFFER], |
608 current_.scopes[Scope::MC_CLEAR_STRING_TABLE], | 606 current_.scopes[Scope::MC_CLEAR_STRING_TABLE], |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 ContextDisposalRateInMilliseconds(), | 650 ContextDisposalRateInMilliseconds(), |
653 CompactionSpeedInBytesPerMillisecond()); | 651 CompactionSpeedInBytesPerMillisecond()); |
654 break; | 652 break; |
655 case Event::START: | 653 case Event::START: |
656 break; | 654 break; |
657 default: | 655 default: |
658 UNREACHABLE(); | 656 UNREACHABLE(); |
659 } | 657 } |
660 } | 658 } |
661 | 659 |
662 int GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer, | 660 double GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer, |
663 const BytesAndDuration& initial, double time_ms) { | 661 const BytesAndDuration& initial, double time_ms) { |
664 BytesAndDuration sum = buffer.Sum( | 662 BytesAndDuration sum = buffer.Sum( |
665 [time_ms](BytesAndDuration a, BytesAndDuration b) { | 663 [time_ms](BytesAndDuration a, BytesAndDuration b) { |
666 if (time_ms != 0 && a.second >= time_ms) return a; | 664 if (time_ms != 0 && a.second >= time_ms) return a; |
667 return std::make_pair(a.first + b.first, a.second + b.second); | 665 return std::make_pair(a.first + b.first, a.second + b.second); |
668 }, | 666 }, |
669 initial); | 667 initial); |
670 uint64_t bytes = sum.first; | 668 uint64_t bytes = sum.first; |
671 double durations = sum.second; | 669 double durations = sum.second; |
672 if (durations == 0.0) return 0; | 670 if (durations == 0.0) return 0; |
673 double speed = bytes / durations + 0.5; | 671 double speed = bytes / durations; |
674 const int max_speed = 1024 * MB; | 672 const int max_speed = 1024 * MB; |
675 const int min_speed = 1; | 673 const int min_speed = 1; |
676 if (speed >= max_speed) return max_speed; | 674 if (speed >= max_speed) return max_speed; |
677 if (speed <= min_speed) return min_speed; | 675 if (speed <= min_speed) return min_speed; |
678 return static_cast<int>(speed); | 676 return speed; |
679 } | 677 } |
680 | 678 |
681 int GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer) { | 679 double GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer) { |
682 return AverageSpeed(buffer, MakeBytesAndDuration(0, 0), 0); | 680 return AverageSpeed(buffer, MakeBytesAndDuration(0, 0), 0); |
683 } | 681 } |
684 | 682 |
685 intptr_t GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const { | 683 double GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const { |
686 if (cumulative_incremental_marking_duration_ == 0.0) return 0; | 684 if (cumulative_incremental_marking_duration_ == 0.0) return 0; |
687 // We haven't completed an entire round of incremental marking, yet. | 685 // We haven't completed an entire round of incremental marking, yet. |
688 // Use data from GCTracer instead of data from event buffers. | 686 // Use data from GCTracer instead of data from event buffers. |
689 if (recorded_incremental_marking_steps_.Count() == 0) { | 687 if (recorded_incremental_marking_steps_.Count() == 0) { |
690 return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ / | 688 return cumulative_incremental_marking_bytes_ / |
691 cumulative_pure_incremental_marking_duration_); | 689 cumulative_pure_incremental_marking_duration_; |
692 } | 690 } |
693 return AverageSpeed(recorded_incremental_marking_steps_); | 691 return AverageSpeed(recorded_incremental_marking_steps_); |
694 } | 692 } |
695 | 693 |
696 intptr_t GCTracer::ScavengeSpeedInBytesPerMillisecond( | 694 double GCTracer::ScavengeSpeedInBytesPerMillisecond( |
697 ScavengeSpeedMode mode) const { | 695 ScavengeSpeedMode mode) const { |
698 if (mode == kForAllObjects) { | 696 if (mode == kForAllObjects) { |
699 return AverageSpeed(recorded_scavenges_total_); | 697 return AverageSpeed(recorded_scavenges_total_); |
700 } else { | 698 } else { |
701 return AverageSpeed(recorded_scavenges_survived_); | 699 return AverageSpeed(recorded_scavenges_survived_); |
702 } | 700 } |
703 } | 701 } |
704 | 702 |
705 intptr_t GCTracer::CompactionSpeedInBytesPerMillisecond() const { | 703 double GCTracer::CompactionSpeedInBytesPerMillisecond() const { |
706 return AverageSpeed(recorded_compactions_); | 704 return AverageSpeed(recorded_compactions_); |
707 } | 705 } |
708 | 706 |
709 intptr_t GCTracer::MarkCompactSpeedInBytesPerMillisecond() const { | 707 double GCTracer::MarkCompactSpeedInBytesPerMillisecond() const { |
710 return AverageSpeed(recorded_mark_compacts_); | 708 return AverageSpeed(recorded_mark_compacts_); |
711 } | 709 } |
712 | 710 |
713 intptr_t GCTracer::FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() | 711 double GCTracer::FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() const { |
714 const { | |
715 return AverageSpeed(recorded_incremental_mark_compacts_); | 712 return AverageSpeed(recorded_incremental_mark_compacts_); |
716 } | 713 } |
717 | 714 |
718 double GCTracer::CombinedMarkCompactSpeedInBytesPerMillisecond() { | 715 double GCTracer::CombinedMarkCompactSpeedInBytesPerMillisecond() { |
719 if (combined_mark_compact_speed_cache_ > 0) | 716 if (combined_mark_compact_speed_cache_ > 0) |
720 return combined_mark_compact_speed_cache_; | 717 return combined_mark_compact_speed_cache_; |
721 const double kMinimumMarkingSpeed = 0.5; | 718 const double kMinimumMarkingSpeed = 0.5; |
722 double speed1 = | 719 double speed1 = IncrementalMarkingSpeedInBytesPerMillisecond(); |
723 static_cast<double>(IncrementalMarkingSpeedInBytesPerMillisecond()); | 720 double speed2 = FinalIncrementalMarkCompactSpeedInBytesPerMillisecond(); |
724 double speed2 = static_cast<double>( | |
725 FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); | |
726 if (speed1 < kMinimumMarkingSpeed || speed2 < kMinimumMarkingSpeed) { | 721 if (speed1 < kMinimumMarkingSpeed || speed2 < kMinimumMarkingSpeed) { |
727 // No data for the incremental marking speed. | 722 // No data for the incremental marking speed. |
728 // Return the non-incremental mark-compact speed. | 723 // Return the non-incremental mark-compact speed. |
729 combined_mark_compact_speed_cache_ = | 724 combined_mark_compact_speed_cache_ = |
730 static_cast<double>(MarkCompactSpeedInBytesPerMillisecond()); | 725 MarkCompactSpeedInBytesPerMillisecond(); |
731 } else { | 726 } else { |
732 // Combine the speed of incremental step and the speed of the final step. | 727 // Combine the speed of incremental step and the speed of the final step. |
733 // 1 / (1 / speed1 + 1 / speed2) = speed1 * speed2 / (speed1 + speed2). | 728 // 1 / (1 / speed1 + 1 / speed2) = speed1 * speed2 / (speed1 + speed2). |
734 combined_mark_compact_speed_cache_ = speed1 * speed2 / (speed1 + speed2); | 729 combined_mark_compact_speed_cache_ = speed1 * speed2 / (speed1 + speed2); |
735 } | 730 } |
736 return combined_mark_compact_speed_cache_; | 731 return combined_mark_compact_speed_cache_; |
737 } | 732 } |
738 | 733 |
739 double GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond( | 734 double GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond( |
740 double time_ms) const { | 735 double time_ms) const { |
(...skipping 10 matching lines...) Expand all Loading... |
751 return AverageSpeed(recorded_old_generation_allocations_, | 746 return AverageSpeed(recorded_old_generation_allocations_, |
752 MakeBytesAndDuration(bytes, durations), time_ms); | 747 MakeBytesAndDuration(bytes, durations), time_ms); |
753 } | 748 } |
754 | 749 |
755 double GCTracer::AllocationThroughputInBytesPerMillisecond( | 750 double GCTracer::AllocationThroughputInBytesPerMillisecond( |
756 double time_ms) const { | 751 double time_ms) const { |
757 return NewSpaceAllocationThroughputInBytesPerMillisecond(time_ms) + | 752 return NewSpaceAllocationThroughputInBytesPerMillisecond(time_ms) + |
758 OldGenerationAllocationThroughputInBytesPerMillisecond(time_ms); | 753 OldGenerationAllocationThroughputInBytesPerMillisecond(time_ms); |
759 } | 754 } |
760 | 755 |
761 | 756 double GCTracer::CurrentAllocationThroughputInBytesPerMillisecond() const { |
762 size_t GCTracer::CurrentAllocationThroughputInBytesPerMillisecond() const { | |
763 return AllocationThroughputInBytesPerMillisecond(kThroughputTimeFrameMs); | 757 return AllocationThroughputInBytesPerMillisecond(kThroughputTimeFrameMs); |
764 } | 758 } |
765 | 759 |
766 | 760 double GCTracer::CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() |
767 size_t GCTracer::CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() | |
768 const { | 761 const { |
769 return OldGenerationAllocationThroughputInBytesPerMillisecond( | 762 return OldGenerationAllocationThroughputInBytesPerMillisecond( |
770 kThroughputTimeFrameMs); | 763 kThroughputTimeFrameMs); |
771 } | 764 } |
772 | 765 |
773 double GCTracer::ContextDisposalRateInMilliseconds() const { | 766 double GCTracer::ContextDisposalRateInMilliseconds() const { |
774 if (recorded_context_disposal_times_.Count() < | 767 if (recorded_context_disposal_times_.Count() < |
775 recorded_context_disposal_times_.kSize) | 768 recorded_context_disposal_times_.kSize) |
776 return 0.0; | 769 return 0.0; |
777 double begin = heap_->MonotonicallyIncreasingTimeInMs(); | 770 double begin = heap_->MonotonicallyIncreasingTimeInMs(); |
778 double end = recorded_context_disposal_times_.Sum( | 771 double end = recorded_context_disposal_times_.Sum( |
779 [](double a, double b) { return b; }, 0.0); | 772 [](double a, double b) { return b; }, 0.0); |
780 return (begin - end) / recorded_context_disposal_times_.Count(); | 773 return (begin - end) / recorded_context_disposal_times_.Count(); |
781 } | 774 } |
782 | 775 |
783 double GCTracer::AverageSurvivalRatio() const { | 776 double GCTracer::AverageSurvivalRatio() const { |
784 if (recorded_survival_ratios_.Count() == 0) return 0.0; | 777 if (recorded_survival_ratios_.Count() == 0) return 0.0; |
785 double sum = recorded_survival_ratios_.Sum( | 778 double sum = recorded_survival_ratios_.Sum( |
786 [](double a, double b) { return a + b; }, 0.0); | 779 [](double a, double b) { return a + b; }, 0.0); |
787 return sum / recorded_survival_ratios_.Count(); | 780 return sum / recorded_survival_ratios_.Count(); |
788 } | 781 } |
789 | 782 |
790 bool GCTracer::SurvivalEventsRecorded() const { | 783 bool GCTracer::SurvivalEventsRecorded() const { |
791 return recorded_survival_ratios_.Count() > 0; | 784 return recorded_survival_ratios_.Count() > 0; |
792 } | 785 } |
793 | 786 |
794 void GCTracer::ResetSurvivalEvents() { recorded_survival_ratios_.Reset(); } | 787 void GCTracer::ResetSurvivalEvents() { recorded_survival_ratios_.Reset(); } |
795 } // namespace internal | 788 } // namespace internal |
796 } // namespace v8 | 789 } // namespace v8 |
OLD | NEW |