Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: runtime/vm/pages.cc

Issue 235343004: Accelerate old-space growth (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/pages.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "vm/object.h" 11 #include "vm/object.h"
12 #include "vm/virtual_memory.h" 12 #include "vm/virtual_memory.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 DEFINE_FLAG(int, heap_growth_space_ratio, 20, 16 DEFINE_FLAG(int, heap_growth_space_ratio, 20,
17 "The desired maximum percentage of free space after GC"); 17 "The desired maximum percentage of free space after GC");
18 DEFINE_FLAG(int, heap_growth_time_ratio, 3, 18 DEFINE_FLAG(int, heap_growth_time_ratio, 3,
19 "The desired maximum percentage of time spent in GC"); 19 "The desired maximum percentage of time spent in GC");
20 DEFINE_FLAG(int, heap_growth_rate, 4, 20 DEFINE_FLAG(int, heap_growth_rate, 256,
21 "The size the heap is grown, in heap pages"); 21 "The max number of pages the heap can grow at a time");
22 DEFINE_FLAG(bool, print_free_list_before_gc, false, 22 DEFINE_FLAG(bool, print_free_list_before_gc, false,
23 "Print free list statistics before a GC"); 23 "Print free list statistics before a GC");
24 DEFINE_FLAG(bool, print_free_list_after_gc, false, 24 DEFINE_FLAG(bool, print_free_list_after_gc, false,
25 "Print free list statistics after a GC"); 25 "Print free list statistics after a GC");
26 DEFINE_FLAG(bool, collect_code, true, 26 DEFINE_FLAG(bool, collect_code, true,
27 "Attempt to GC infrequently used code."); 27 "Attempt to GC infrequently used code.");
28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000, 28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
29 "Time between attempts to collect unused code."); 29 "Time between attempts to collect unused code.");
30 DEFINE_FLAG(bool, log_code_drop, false, 30 DEFINE_FLAG(bool, log_code_drop, false,
31 "Emit a log message when pointers to unused code are dropped."); 31 "Emit a log message when pointers to unused code are dropped.");
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 OS::PrintErr(" done.\n"); 627 OS::PrintErr(" done.\n");
628 } 628 }
629 629
630 // Done, reset the marker. 630 // Done, reset the marker.
631 ASSERT(sweeping_); 631 ASSERT(sweeping_);
632 sweeping_ = false; 632 sweeping_ = false;
633 } 633 }
634 634
635 635
636 PageSpaceController::PageSpaceController(int heap_growth_ratio, 636 PageSpaceController::PageSpaceController(int heap_growth_ratio,
637 int heap_growth_rate, 637 int heap_growth_max,
638 int garbage_collection_time_ratio) 638 int garbage_collection_time_ratio)
639 : is_enabled_(false), 639 : is_enabled_(false),
640 grow_heap_(heap_growth_rate), 640 grow_heap_(heap_growth_max / 2),
641 heap_growth_ratio_(heap_growth_ratio), 641 heap_growth_ratio_(heap_growth_ratio),
642 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), 642 desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
643 heap_growth_rate_(heap_growth_rate), 643 heap_growth_max_(heap_growth_max),
644 garbage_collection_time_ratio_(garbage_collection_time_ratio), 644 garbage_collection_time_ratio_(garbage_collection_time_ratio),
645 last_code_collection_in_us_(OS::GetCurrentTimeMicros()) { 645 last_code_collection_in_us_(OS::GetCurrentTimeMicros()) {
646 } 646 }
647 647
648 648
649 PageSpaceController::~PageSpaceController() {} 649 PageSpaceController::~PageSpaceController() {}
650 650
651 651
652 bool PageSpaceController::NeedsGarbageCollection(SpaceUsage after) const { 652 bool PageSpaceController::NeedsGarbageCollection(SpaceUsage after) const {
653 if (!is_enabled_) { 653 if (!is_enabled_) {
654 return false; 654 return false;
655 } 655 }
656 if (heap_growth_ratio_ == 100) { 656 if (heap_growth_ratio_ == 100) {
657 return false; 657 return false;
658 } 658 }
659 intptr_t capacity_increase_in_words = 659 intptr_t capacity_increase_in_words =
660 after.capacity_in_words - last_usage_.capacity_in_words; 660 after.capacity_in_words - last_usage_.capacity_in_words;
661 ASSERT(capacity_increase_in_words >= 0); 661 ASSERT(capacity_increase_in_words >= 0);
662 capacity_increase_in_words = 662 capacity_increase_in_words =
663 Utils::RoundUp(capacity_increase_in_words, PageSpace::kPageSizeInWords); 663 Utils::RoundUp(capacity_increase_in_words, PageSpace::kPageSizeInWords);
664 intptr_t capacity_increase_in_pages = 664 intptr_t capacity_increase_in_pages =
665 capacity_increase_in_words / PageSpace::kPageSizeInWords; 665 capacity_increase_in_words / PageSpace::kPageSizeInWords;
666 return capacity_increase_in_pages > grow_heap_; 666 double multiplier = 1.0;
667 // To avoid waste, the first GC should be triggered before too long. After
668 // kInitialTimeoutSeconds, gradually lower the capacity limit.
669 static const double kInitialTimeoutSeconds = 1.00;
670 if (history_.IsEmpty()) {
671 double seconds_since_init = MicrosecondsToSeconds(
672 OS::GetCurrentTimeMicros() - Isolate::Current()->start_time());
673 if (seconds_since_init > kInitialTimeoutSeconds) {
674 multiplier = seconds_since_init / kInitialTimeoutSeconds;
675 }
676 }
677 return capacity_increase_in_pages * multiplier > grow_heap_;
667 } 678 }
668 679
669 680
670 void PageSpaceController::EvaluateGarbageCollection( 681 void PageSpaceController::EvaluateGarbageCollection(
671 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { 682 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) {
672 // TODO(iposva): Reevaluate the growth policies. 683 Heap* heap = Isolate::Current()->heap();
Ivan Posva 2014/04/24 17:44:18 The PSC should remember the heap it is associated
koda 2014/04/24 18:07:45 I'll do this in a follow-up Isolate::Current clean
673 intptr_t before_total_in_words =
674 before.used_in_words + before.external_in_words;
675 intptr_t after_total_in_words =
676 after.used_in_words + after.external_in_words;
677 ASSERT(before_total_in_words >= after_total_in_words);
678 ASSERT(end >= start); 684 ASSERT(end >= start);
679 history_.AddGarbageCollectionTime(start, end); 685 history_.AddGarbageCollectionTime(start, end);
680 int collected_garbage_ratio = static_cast<int>( 686 int gc_time_fraction = history_.GarbageCollectionTimeFraction();
681 (static_cast<double>(before_total_in_words - after_total_in_words) / 687 heap->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction);
682 static_cast<double>(before_total_in_words))
683 * 100.0);
684 bool enough_free_space =
685 (collected_garbage_ratio >= heap_growth_ratio_);
686 int garbage_collection_time_fraction =
687 history_.GarbageCollectionTimeFraction();
688 bool enough_free_time =
689 (garbage_collection_time_fraction <= garbage_collection_time_ratio_);
690 688
691 Heap* heap = Isolate::Current()->heap(); 689 // Assume garbage increases linearly with allocation:
692 if (enough_free_space && enough_free_time) { 690 // G = kA, and estimate k from the previous cycle.
693 grow_heap_ = 0; 691 intptr_t allocated_since_previous_gc =
694 } else { 692 before.used_in_words - last_usage_.used_in_words;
695 intptr_t used_target = static_cast<intptr_t>( 693 intptr_t garbage = before.used_in_words - after.used_in_words;
696 after_total_in_words / desired_utilization_); 694 double k = garbage / static_cast<double>(allocated_since_previous_gc);
697 intptr_t capacity_growth_in_words = 695 heap->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100));
698 Utils::RoundUp(Utils::Maximum(static_cast<intptr_t>(0), 696
699 used_target - after.capacity_in_words), 697 // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage.
700 PageSpace::kPageSizeInWords); 698 double t = 1.0 - desired_utilization_;
701 int capacity_growth_in_pages = 699 // If we spend too much time in GC, strive for even more free space.
702 capacity_growth_in_words / PageSpace::kPageSizeInWords; 700 if (gc_time_fraction > garbage_collection_time_ratio_) {
703 grow_heap_ = Utils::Maximum(capacity_growth_in_pages, heap_growth_rate_); 701 t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0;
704 heap->RecordData(PageSpace::kPageGrowth, capacity_growth_in_pages);
705 } 702 }
703
704 // Find minimum 'grow_heap_' such that after increasing capacity by
705 // '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_) {
707 intptr_t limit =
708 after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords);
709 intptr_t allocated_before_next_gc = limit - after.used_in_words;
710 double estimated_garbage = k * allocated_before_next_gc;
711 if (t <= estimated_garbage / limit) {
712 break;
713 }
714 }
715 heap->RecordData(PageSpace::kPageGrowth, grow_heap_);
716
706 // Limit shrinkage: allow growth by at least half the pages freed by GC. 717 // Limit shrinkage: allow growth by at least half the pages freed by GC.
707 intptr_t freed_pages = 718 intptr_t freed_pages =
708 (before.capacity_in_words - after.capacity_in_words) / 719 (before.capacity_in_words - after.capacity_in_words) /
709 PageSpace::kPageSizeInWords; 720 PageSpace::kPageSizeInWords;
710 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); 721 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2);
711 heap->RecordData(PageSpace::kGarbageRatio, collected_garbage_ratio);
712 heap->RecordData(PageSpace::kGCTimeFraction,
713 garbage_collection_time_fraction);
714 heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_); 722 heap->RecordData(PageSpace::kAllowedGrowth, grow_heap_);
715 last_usage_ = after; 723 last_usage_ = after;
716 } 724 }
717 725
718 726
719 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory() 727 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory()
720 : index_(0) { 728 : index_(0) {
721 for (intptr_t i = 0; i < kHistoryLength; i++) { 729 for (intptr_t i = 0; i < kHistoryLength; i++) {
722 start_[i] = 0; 730 start_[i] = 0;
723 end_[i] = 0; 731 end_[i] = 0;
(...skipping 29 matching lines...) Expand all
753 return 0; 761 return 0;
754 } else { 762 } else {
755 ASSERT(total_time >= gc_time); 763 ASSERT(total_time >= gc_time);
756 int result= static_cast<int>((static_cast<double>(gc_time) / 764 int result= static_cast<int>((static_cast<double>(gc_time) /
757 static_cast<double>(total_time)) * 100); 765 static_cast<double>(total_time)) * 100);
758 return result; 766 return result;
759 } 767 }
760 } 768 }
761 769
762 } // namespace dart 770 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/pages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698