| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/pages.h" | 5 #include "vm/pages.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/compiler_stats.h" | 8 #include "vm/compiler_stats.h" |
| 9 #include "vm/gc_marker.h" | 9 #include "vm/gc_marker.h" |
| 10 #include "vm/gc_sweeper.h" | 10 #include "vm/gc_sweeper.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 118 |
| 119 | 119 |
| 120 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words) | 120 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words) |
| 121 : freelist_(), | 121 : freelist_(), |
| 122 heap_(heap), | 122 heap_(heap), |
| 123 pages_(NULL), | 123 pages_(NULL), |
| 124 pages_tail_(NULL), | 124 pages_tail_(NULL), |
| 125 large_pages_(NULL), | 125 large_pages_(NULL), |
| 126 max_capacity_in_words_(max_capacity_in_words), | 126 max_capacity_in_words_(max_capacity_in_words), |
| 127 sweeping_(false), | 127 sweeping_(false), |
| 128 page_space_controller_(FLAG_heap_growth_space_ratio, | 128 page_space_controller_(heap, |
| 129 FLAG_heap_growth_space_ratio, |
| 129 FLAG_heap_growth_rate, | 130 FLAG_heap_growth_rate, |
| 130 FLAG_heap_growth_time_ratio), | 131 FLAG_heap_growth_time_ratio), |
| 131 gc_time_micros_(0), | 132 gc_time_micros_(0), |
| 132 collections_(0) { | 133 collections_(0) { |
| 133 } | 134 } |
| 134 | 135 |
| 135 | 136 |
| 136 PageSpace::~PageSpace() { | 137 PageSpace::~PageSpace() { |
| 137 FreePages(pages_); | 138 FreePages(pages_); |
| 138 FreePages(large_pages_); | 139 FreePages(large_pages_); |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 heap_->Verify(); | 627 heap_->Verify(); |
| 627 OS::PrintErr(" done.\n"); | 628 OS::PrintErr(" done.\n"); |
| 628 } | 629 } |
| 629 | 630 |
| 630 // Done, reset the marker. | 631 // Done, reset the marker. |
| 631 ASSERT(sweeping_); | 632 ASSERT(sweeping_); |
| 632 sweeping_ = false; | 633 sweeping_ = false; |
| 633 } | 634 } |
| 634 | 635 |
| 635 | 636 |
| 636 PageSpaceController::PageSpaceController(int heap_growth_ratio, | 637 PageSpaceController::PageSpaceController(Heap* heap, |
| 638 int heap_growth_ratio, |
| 637 int heap_growth_max, | 639 int heap_growth_max, |
| 638 int garbage_collection_time_ratio) | 640 int garbage_collection_time_ratio) |
| 639 : is_enabled_(false), | 641 : heap_(heap), |
| 642 is_enabled_(false), |
| 640 grow_heap_(heap_growth_max / 2), | 643 grow_heap_(heap_growth_max / 2), |
| 641 heap_growth_ratio_(heap_growth_ratio), | 644 heap_growth_ratio_(heap_growth_ratio), |
| 642 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), | 645 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), |
| 643 heap_growth_max_(heap_growth_max), | 646 heap_growth_max_(heap_growth_max), |
| 644 garbage_collection_time_ratio_(garbage_collection_time_ratio), | 647 garbage_collection_time_ratio_(garbage_collection_time_ratio), |
| 645 last_code_collection_in_us_(OS::GetCurrentTimeMicros()) { | 648 last_code_collection_in_us_(OS::GetCurrentTimeMicros()) { |
| 646 } | 649 } |
| 647 | 650 |
| 648 | 651 |
| 649 PageSpaceController::~PageSpaceController() {} | 652 PageSpaceController::~PageSpaceController() {} |
| (...skipping 12 matching lines...) Expand all Loading... |
| 662 capacity_increase_in_words = | 665 capacity_increase_in_words = |
| 663 Utils::RoundUp(capacity_increase_in_words, PageSpace::kPageSizeInWords); | 666 Utils::RoundUp(capacity_increase_in_words, PageSpace::kPageSizeInWords); |
| 664 intptr_t capacity_increase_in_pages = | 667 intptr_t capacity_increase_in_pages = |
| 665 capacity_increase_in_words / PageSpace::kPageSizeInWords; | 668 capacity_increase_in_words / PageSpace::kPageSizeInWords; |
| 666 double multiplier = 1.0; | 669 double multiplier = 1.0; |
| 667 // To avoid waste, the first GC should be triggered before too long. After | 670 // To avoid waste, the first GC should be triggered before too long. After |
| 668 // kInitialTimeoutSeconds, gradually lower the capacity limit. | 671 // kInitialTimeoutSeconds, gradually lower the capacity limit. |
| 669 static const double kInitialTimeoutSeconds = 1.00; | 672 static const double kInitialTimeoutSeconds = 1.00; |
| 670 if (history_.IsEmpty()) { | 673 if (history_.IsEmpty()) { |
| 671 double seconds_since_init = MicrosecondsToSeconds( | 674 double seconds_since_init = MicrosecondsToSeconds( |
| 672 OS::GetCurrentTimeMicros() - Isolate::Current()->start_time()); | 675 OS::GetCurrentTimeMicros() - heap_->isolate()->start_time()); |
| 673 if (seconds_since_init > kInitialTimeoutSeconds) { | 676 if (seconds_since_init > kInitialTimeoutSeconds) { |
| 674 multiplier *= seconds_since_init / kInitialTimeoutSeconds; | 677 multiplier *= seconds_since_init / kInitialTimeoutSeconds; |
| 675 } | 678 } |
| 676 } | 679 } |
| 677 return capacity_increase_in_pages * multiplier > grow_heap_; | 680 return capacity_increase_in_pages * multiplier > grow_heap_; |
| 678 } | 681 } |
| 679 | 682 |
| 680 | 683 |
| 681 void PageSpaceController::EvaluateGarbageCollection( | 684 void PageSpaceController::EvaluateGarbageCollection( |
| 682 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { | 685 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { |
| 683 Heap* heap = Isolate::Current()->heap(); | |
| 684 ASSERT(end >= start); | 686 ASSERT(end >= start); |
| 685 history_.AddGarbageCollectionTime(start, end); | 687 history_.AddGarbageCollectionTime(start, end); |
| 686 int gc_time_fraction = history_.GarbageCollectionTimeFraction(); | 688 int gc_time_fraction = history_.GarbageCollectionTimeFraction(); |
| 687 heap->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); | 689 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); |
| 688 | 690 |
| 689 // Assume garbage increases linearly with allocation: | 691 // Assume garbage increases linearly with allocation: |
| 690 // G = kA, and estimate k from the previous cycle. | 692 // G = kA, and estimate k from the previous cycle. |
| 691 intptr_t allocated_since_previous_gc = | 693 intptr_t allocated_since_previous_gc = |
| 692 before.used_in_words - last_usage_.used_in_words; | 694 before.used_in_words - last_usage_.used_in_words; |
| 693 intptr_t garbage = before.used_in_words - after.used_in_words; | 695 intptr_t garbage = before.used_in_words - after.used_in_words; |
| 694 double k = garbage / static_cast<double>(allocated_since_previous_gc); | 696 double k = garbage / static_cast<double>(allocated_since_previous_gc); |
| 695 heap->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100)); | 697 heap_->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100)); |
| 696 | 698 |
| 697 // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage. | 699 // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage. |
| 698 double t = 1.0 - desired_utilization_; | 700 double t = 1.0 - desired_utilization_; |
| 699 // If we spend too much time in GC, strive for even more free space. | 701 // If we spend too much time in GC, strive for even more free space. |
| 700 if (gc_time_fraction > garbage_collection_time_ratio_) { | 702 if (gc_time_fraction > garbage_collection_time_ratio_) { |
| 701 t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0; | 703 t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0; |
| 702 } | 704 } |
| 703 | 705 |
| 704 // Find minimum 'grow_heap_' such that after increasing capacity by | 706 // Find minimum 'grow_heap_' such that after increasing capacity by |
| 705 // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. | 707 // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. |
| 706 for (grow_heap_ = 0; grow_heap_ < heap_growth_max_; ++grow_heap_) { | 708 for (grow_heap_ = 0; grow_heap_ < heap_growth_max_; ++grow_heap_) { |
| 707 intptr_t limit = | 709 intptr_t limit = |
| 708 after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); | 710 after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); |
| 709 intptr_t allocated_before_next_gc = limit - after.used_in_words; | 711 intptr_t allocated_before_next_gc = limit - after.used_in_words; |
| 710 double estimated_garbage = k * allocated_before_next_gc; | 712 double estimated_garbage = k * allocated_before_next_gc; |
| 711 if (t <= estimated_garbage / limit) { | 713 if (t <= estimated_garbage / limit) { |
| 712 break; | 714 break; |
| 713 } | 715 } |
| 714 } | 716 } |
| 715 heap->RecordData(PageSpace::kPageGrowth, grow_heap_); | 717 heap_->RecordData(PageSpace::kPageGrowth, grow_heap_); |
| 716 | 718 |
| 717 // Limit shrinkage: allow growth by at least half the pages freed by GC. | 719 // Limit shrinkage: allow growth by at least half the pages freed by GC. |
| 718 intptr_t freed_pages = | 720 intptr_t freed_pages = |
| 719 (before.capacity_in_words - after.capacity_in_words) / | 721 (before.capacity_in_words - after.capacity_in_words) / |
| 720 PageSpace::kPageSizeInWords; | 722 PageSpace::kPageSizeInWords; |
| 721 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); | 723 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); |
| 722 heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_); | 724 heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_); |
| 723 last_usage_ = after; | 725 last_usage_ = after; |
| 724 } | 726 } |
| 725 | 727 |
| 726 | 728 |
| 727 void PageSpaceGarbageCollectionHistory:: | 729 void PageSpaceGarbageCollectionHistory:: |
| 728 AddGarbageCollectionTime(int64_t start, int64_t end) { | 730 AddGarbageCollectionTime(int64_t start, int64_t end) { |
| 729 Entry entry; | 731 Entry entry; |
| 730 entry.start = start; | 732 entry.start = start; |
| 731 entry.end = end; | 733 entry.end = end; |
| 732 history_.Add(entry); | 734 history_.Add(entry); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 746 return 0; | 748 return 0; |
| 747 } else { | 749 } else { |
| 748 ASSERT(total_time >= gc_time); | 750 ASSERT(total_time >= gc_time); |
| 749 int result= static_cast<int>((static_cast<double>(gc_time) / | 751 int result= static_cast<int>((static_cast<double>(gc_time) / |
| 750 static_cast<double>(total_time)) * 100); | 752 static_cast<double>(total_time)) * 100); |
| 751 return result; | 753 return result; |
| 752 } | 754 } |
| 753 } | 755 } |
| 754 | 756 |
| 755 } // namespace dart | 757 } // namespace dart |
| OLD | NEW |