< prev index next >

src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp

Print this page




  35   NumberSeq _allocation_rate_bytes;
  36   NumberSeq _reclamation_rate_bytes;
  37 
  38   size_t _bytes_allocated_since_CM;
  39   size_t _bytes_reclaimed_this_cycle;
  40 
  41 protected:
  42   typedef struct {
  43     size_t region_number;
  44     size_t garbage;
  45   } RegionGarbage;
  46 
  47   static int compare_by_garbage(RegionGarbage a, RegionGarbage b) {
  48     if (a.garbage > b.garbage)
  49       return -1;
  50     else if (b.garbage < a.garbage)
  51       return 1;
  52     else return 0;
  53   }
  54 












  55   RegionGarbage* _region_garbage;
  56   size_t _region_garbage_size;
  57 
  58   size_t _bytes_allocated_start_CM;
  59   size_t _bytes_allocated_during_CM;
  60 
  61   size_t _bytes_allocated_after_last_gc;
  62 
  63   uint _cancelled_cm_cycles_in_a_row;
  64   uint _successful_cm_cycles_in_a_row;
  65 
  66   size_t _bytes_in_cset;
  67 
  68 public:
  69 
  70   ShenandoahHeuristics();
  71   ~ShenandoahHeuristics();
  72 
  73   void record_bytes_allocated(size_t bytes);
  74   void record_bytes_reclaimed(size_t bytes);


 157   _region_garbage_size(0)
 158 {
 159 }
 160 
 161 ShenandoahHeuristics::~ShenandoahHeuristics() {
 162   if (_region_garbage != NULL) {
 163     FREE_C_HEAP_ARRAY(RegionGarbage, _region_garbage);
 164   }
 165 }
 166 
 167 void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set, int* connections) {
 168   start_choose_collection_set();
 169 
 170   ShenandoahHeap* heap = ShenandoahHeap::heap();
 171 
 172   // Step 1. Build up the region candidates we care about, rejecting losers and accepting winners right away.
 173 
 174   ShenandoahHeapRegionSet* regions = heap->regions();
 175   size_t active = regions->active_regions();
 176 
 177   RegionGarbage* candidates = _region_garbage;
 178   if (candidates == NULL) {
 179     candidates = NEW_C_HEAP_ARRAY(RegionGarbage, active, mtGC);
 180     _region_garbage_size = active;
 181   } else if (_region_garbage_size < active) {
 182     REALLOC_C_HEAP_ARRAY(RegionGarbage, _region_garbage, active, mtGC);
 183     _region_garbage_size = active;
 184   }
 185 
 186   size_t cand_idx = 0;
 187   _bytes_in_cset = 0;
 188 
 189   size_t immediate_garbage = 0;
 190   size_t immediate_regions = 0;
 191   for (size_t i = 0; i < active; i++) {
 192     ShenandoahHeapRegion* region = regions->get(i);
 193 
 194     if (! region->is_humongous() && ! region->is_pinned()) {
 195       if ((! region->is_empty()) && ! region->has_live()) {
 196         // We can recycle it right away and put it in the free set.
 197         immediate_regions++;
 198         immediate_garbage += region->garbage();
 199         heap->decrease_used(region->used());
 200         region->recycle();
 201         log_develop_trace(gc)("Choose region " SIZE_FORMAT " for immediate reclaim with garbage = " SIZE_FORMAT
 202                               " and live = " SIZE_FORMAT "\n",
 203                               region->region_number(), region->garbage(), region->get_live_data_bytes());
 204       } else {
 205         // This is our candidate for later consideration.
 206         candidates[cand_idx].region_number = region->region_number();
 207         candidates[cand_idx].garbage = region->garbage();
 208         cand_idx++;
 209       }
 210     } else {
 211       assert(region->has_live() || region->is_empty() || region->is_pinned() || region->is_humongous(), "check rejected");
 212       log_develop_trace(gc)("Rejected region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
 213                             " and live = " SIZE_FORMAT "\n",
 214                             region->region_number(), region->garbage(), region->get_live_data_bytes());
 215     }
 216   }
 217 
 218   // Step 2. Process the remanining candidates, if any.
 219 
 220   if (cand_idx > 0) {
 221     if (needs_regions_sorted_by_garbage()) {
 222       QuickSort::sort<RegionGarbage>(candidates, cand_idx, compare_by_garbage, false);
 223     }
 224 
 225     for (size_t i = 0; i < cand_idx; i++) {
 226       ShenandoahHeapRegion *region = regions->get_fast(candidates[i].region_number);
 227       if (region_in_collection_set(region, immediate_garbage)) {
 228         log_develop_trace(gc)("Choose region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
 229                                       " and live = " SIZE_FORMAT "\n",
 230                               region->region_number(), region->garbage(), region->get_live_data_bytes());
 231         collection_set->add_region(region);
 232         region->set_in_collection_set(true);
 233         _bytes_in_cset += region->used();
 234       }
 235     }
 236   }
 237 
 238   end_choose_collection_set();
 239 
 240   size_t total_garbage = heap->garbage();
 241   log_debug(gc)("Total Garbage: "SIZE_FORMAT, total_garbage);
 242   log_debug(gc)("Immediate Garbage: "SIZE_FORMAT, immediate_garbage);


 564   double _garbage_threshold_factor;
 565   double _allocation_threshold_factor;
 566 
 567   uintx _used_threshold;
 568   uintx _garbage_threshold;
 569   uintx _allocation_threshold;
 570 
 571 public:
 572   ConnectionHeuristics() : ShenandoahHeuristics() {
 573     _max_live_data = 0;
 574 
 575     _used_threshold = 0;
 576     _garbage_threshold = 0;
 577     _allocation_threshold = 0;
 578 
 579     _used_threshold_factor = 0.;
 580     _garbage_threshold_factor = 0.1;
 581     _allocation_threshold_factor = 0.;
 582   }
 583 
 584   virtual ~ConnectionHeuristics() {}
 585 
 586   virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
 587     size_t half_gig = 64 * 1024 * 1024;
 588     size_t bytes_alloc = ShenandoahHeap::heap()->bytes_allocated_since_cm();
 589     bool result =  bytes_alloc > half_gig;
 590     if (result) tty->print("Starting a concurrent mark");
 591     return result;
 592   }
 593 
 594   bool maybe_add_heap_region(ShenandoahHeapRegion* hr, ShenandoahCollectionSet* collection_set) {
 595     if (!hr->is_humongous() && hr->has_live() && !collection_set->contains(hr)) {
 596       collection_set->add_region_check_for_duplicates(hr);
 597       hr->set_in_collection_set(true);
 598       return true;
 599     }
 600     return false;
 601   }
 602 
 603   virtual void choose_collection_set(ShenandoahCollectionSet* collection_set, int* connections) {
 604     ShenandoahHeapRegionSet* regions = ShenandoahHeap::heap()->regions();
 605     size_t end = regions->active_regions();
 606     RegionGarbage sorted_by_garbage[end];
 607     for (size_t i = 0; i < end; i++) {

 608       ShenandoahHeapRegion* r = regions->get_fast(i);
 609       sorted_by_garbage[i].region_number = r->region_number();
 610       sorted_by_garbage[i].garbage = r->garbage();
 611     }
 612 
 613     QuickSort::sort<RegionGarbage>(sorted_by_garbage, end, compare_by_garbage, false);
 614 
 615     int num = ShenandoahHeap::heap()->num_regions();
 616     // simulate write heuristics by picking best region.
 617     int r = 0;
 618     ShenandoahHeapRegion* choosenOne = regions->get(sorted_by_garbage[0].region_number);
 619 
 620     while (! maybe_add_heap_region(choosenOne, collection_set)) {
 621       choosenOne = regions->get(sorted_by_garbage[++r].region_number);
 622     }
 623 
 624     int region_number = choosenOne->region_number();
 625     log_develop_trace(gc)("Adding choosen region %d\n", region_number);
 626 
 627     // Add all the regions which point to this region.
 628     for (int i = 0; i < num; i++) {
 629       if (connections[i * num + region_number] > 0) {
 630         ShenandoahHeapRegion* candidate = regions->get(sorted_by_garbage[i].region_number);
 631         if (maybe_add_heap_region(candidate, collection_set))
 632           log_develop_trace(gc)("Adding region %d which points to the choosen region\n", i);
 633       }
 634     }
 635 
 636     // Add all the regions they point to.
 637     for (size_t ci = 0; ci < collection_set->active_regions(); ci++) {
 638       ShenandoahHeapRegion* cs_heap_region = collection_set->get(ci);
 639       int cs_heap_region_number = cs_heap_region->region_number();
 640       for (int i = 0; i < num; i++) {
 641         if (connections[i * num + cs_heap_region_number] > 0) {
 642           ShenandoahHeapRegion* candidate = regions->get(sorted_by_garbage[i].region_number);
 643           if (maybe_add_heap_region(candidate, collection_set)) {
 644             log_develop_trace(gc)
 645               ("Adding region %d which is pointed to by region %d\n", i, cs_heap_region_number);
 646           }
 647         }
 648       }
 649     }
 650     _max_live_data = MAX2(_max_live_data, collection_set->live_data());
 651     collection_set->print();
 652   }
 653 
 654   virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
 655     assert(false, "Shouldn't get here");
 656     return false;
 657   }
 658 };
 659 class PartialHeuristics : public AdaptiveHeuristics {
 660 public:
 661   PartialHeuristics() : AdaptiveHeuristics() {
 662     if (FLAG_IS_DEFAULT(ShenandoahAllocationThreshold)) {
 663       FLAG_SET_DEFAULT(ShenandoahAllocationThreshold, 5);
 664     }
 665     FLAG_SET_DEFAULT(UseShenandoahMatrix, true);




  35   NumberSeq _allocation_rate_bytes;
  36   NumberSeq _reclamation_rate_bytes;
  37 
  38   size_t _bytes_allocated_since_CM;
  39   size_t _bytes_reclaimed_this_cycle;
  40 
  41 protected:
  42   typedef struct {
  43     size_t region_number;
  44     size_t garbage;
  45   } RegionGarbage;
  46 
  47   static int compare_by_garbage(RegionGarbage a, RegionGarbage b) {
  48     if (a.garbage > b.garbage)
  49       return -1;
  50     else if (b.garbage < a.garbage)
  51       return 1;
  52     else return 0;
  53   }
  54 
  55   RegionGarbage* get_region_garbage_cache(size_t num) {
  56     RegionGarbage* res = _region_garbage;
  57     if (res == NULL) {
  58       res = NEW_C_HEAP_ARRAY(RegionGarbage, num, mtGC);
  59       _region_garbage_size = num;
  60     } else if (_region_garbage_size < num) {
  61       REALLOC_C_HEAP_ARRAY(RegionGarbage, _region_garbage, num, mtGC);
  62       _region_garbage_size = num;
  63     }
  64     return res;
  65   }
  66 
  67   RegionGarbage* _region_garbage;
  68   size_t _region_garbage_size;
  69 
  70   size_t _bytes_allocated_start_CM;
  71   size_t _bytes_allocated_during_CM;
  72 
  73   size_t _bytes_allocated_after_last_gc;
  74 
  75   uint _cancelled_cm_cycles_in_a_row;
  76   uint _successful_cm_cycles_in_a_row;
  77 
  78   size_t _bytes_in_cset;
  79 
  80 public:
  81 
  82   ShenandoahHeuristics();
  83   ~ShenandoahHeuristics();
  84 
  85   void record_bytes_allocated(size_t bytes);
  86   void record_bytes_reclaimed(size_t bytes);


 169   _region_garbage_size(0)
 170 {
 171 }
 172 
 173 ShenandoahHeuristics::~ShenandoahHeuristics() {
 174   if (_region_garbage != NULL) {
 175     FREE_C_HEAP_ARRAY(RegionGarbage, _region_garbage);
 176   }
 177 }
 178 
 179 void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set, int* connections) {
 180   start_choose_collection_set();
 181 
 182   ShenandoahHeap* heap = ShenandoahHeap::heap();
 183 
 184   // Step 1. Build up the region candidates we care about, rejecting losers and accepting winners right away.
 185 
 186   ShenandoahHeapRegionSet* regions = heap->regions();
 187   size_t active = regions->active_regions();
 188 
 189   RegionGarbage* candidates = get_region_garbage_cache(active);







 190 
 191   size_t cand_idx = 0;
 192   _bytes_in_cset = 0;
 193 
 194   size_t immediate_garbage = 0;
 195   size_t immediate_regions = 0;
 196   for (size_t i = 0; i < active; i++) {
 197     ShenandoahHeapRegion* region = regions->get(i);
 198 
 199     if (! region->is_humongous() && ! region->is_pinned()) {
 200       if ((! region->is_empty()) && ! region->has_live()) {
 201         // We can recycle it right away and put it in the free set.
 202         immediate_regions++;
 203         immediate_garbage += region->garbage();
 204         heap->decrease_used(region->used());
 205         region->recycle();
 206         log_develop_trace(gc)("Choose region " SIZE_FORMAT " for immediate reclaim with garbage = " SIZE_FORMAT
 207                               " and live = " SIZE_FORMAT "\n",
 208                               region->region_number(), region->garbage(), region->get_live_data_bytes());
 209       } else {
 210         // This is our candidate for later consideration.
 211         candidates[cand_idx].region_number = region->region_number();
 212         candidates[cand_idx].garbage = region->garbage();
 213         cand_idx++;
 214       }
 215     } else {
 216       assert(region->has_live() || region->is_empty() || region->is_pinned() || region->is_humongous(), "check rejected");
 217       log_develop_trace(gc)("Rejected region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
 218                             " and live = " SIZE_FORMAT "\n",
 219                             region->region_number(), region->garbage(), region->get_live_data_bytes());
 220     }
 221   }
 222 
 223   // Step 2. Process the remanining candidates, if any.
 224 
 225   if (cand_idx > 0) {
 226     if (needs_regions_sorted_by_garbage()) {
 227       QuickSort::sort<RegionGarbage>(candidates, (int)cand_idx, compare_by_garbage, false);
 228     }
 229 
 230     for (size_t i = 0; i < cand_idx; i++) {
 231       ShenandoahHeapRegion *region = regions->get_fast(candidates[i].region_number);
 232       if (region_in_collection_set(region, immediate_garbage)) {
 233         log_develop_trace(gc)("Choose region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
 234                                       " and live = " SIZE_FORMAT "\n",
 235                               region->region_number(), region->garbage(), region->get_live_data_bytes());
 236         collection_set->add_region(region);
 237         region->set_in_collection_set(true);
 238         _bytes_in_cset += region->used();
 239       }
 240     }
 241   }
 242 
 243   end_choose_collection_set();
 244 
 245   size_t total_garbage = heap->garbage();
 246   log_debug(gc)("Total Garbage: "SIZE_FORMAT, total_garbage);
 247   log_debug(gc)("Immediate Garbage: "SIZE_FORMAT, immediate_garbage);


 569   double _garbage_threshold_factor;
 570   double _allocation_threshold_factor;
 571 
 572   uintx _used_threshold;
 573   uintx _garbage_threshold;
 574   uintx _allocation_threshold;
 575 
 576 public:
 577   ConnectionHeuristics() : ShenandoahHeuristics() {
 578     _max_live_data = 0;
 579 
 580     _used_threshold = 0;
 581     _garbage_threshold = 0;
 582     _allocation_threshold = 0;
 583 
 584     _used_threshold_factor = 0.;
 585     _garbage_threshold_factor = 0.1;
 586     _allocation_threshold_factor = 0.;
 587   }
 588 


 589   virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
 590     size_t half_gig = 64 * 1024 * 1024;
 591     size_t bytes_alloc = ShenandoahHeap::heap()->bytes_allocated_since_cm();
 592     bool result =  bytes_alloc > half_gig;
 593     if (result) tty->print("Starting a concurrent mark");
 594     return result;
 595   }
 596 
 597   bool maybe_add_heap_region(ShenandoahHeapRegion* hr, ShenandoahCollectionSet* collection_set) {
 598     if (!hr->is_humongous() && hr->has_live() && !collection_set->contains(hr)) {
 599       collection_set->add_region_check_for_duplicates(hr);
 600       hr->set_in_collection_set(true);
 601       return true;
 602     }
 603     return false;
 604   }
 605 
 606   virtual void choose_collection_set(ShenandoahCollectionSet* collection_set, int* connections) {
 607     ShenandoahHeapRegionSet* regions = ShenandoahHeap::heap()->regions();
 608     size_t active = regions->active_regions();
 609 
 610     RegionGarbage* sorted_by_garbage = get_region_garbage_cache(active);
 611     for (size_t i = 0; i < active; i++) {
 612       ShenandoahHeapRegion* r = regions->get_fast(i);
 613       sorted_by_garbage[i].region_number = r->region_number();
 614       sorted_by_garbage[i].garbage = r->garbage();
 615     }
 616 
 617     QuickSort::sort<RegionGarbage>(sorted_by_garbage, (int) active, compare_by_garbage, false);
 618 
 619     size_t num = ShenandoahHeap::heap()->num_regions();
 620     // simulate write heuristics by picking best region.
 621     int r = 0;
 622     ShenandoahHeapRegion* choosenOne = regions->get(sorted_by_garbage[0].region_number);
 623 
 624     while (! maybe_add_heap_region(choosenOne, collection_set)) {
 625       choosenOne = regions->get(sorted_by_garbage[++r].region_number);
 626     }
 627 
 628     size_t region_number = choosenOne->region_number();
 629     log_develop_trace(gc)("Adding choosen region " SIZE_FORMAT, region_number);
 630 
 631     // Add all the regions which point to this region.
 632     for (size_t i = 0; i < num; i++) {
 633       if (connections[i * num + region_number] > 0) {
 634         ShenandoahHeapRegion* candidate = regions->get(sorted_by_garbage[i].region_number);
 635         if (maybe_add_heap_region(candidate, collection_set))
 636           log_develop_trace(gc)("Adding region " SIZE_FORMAT " which points to the choosen region", i);
 637       }
 638     }
 639 
 640     // Add all the regions they point to.
 641     for (size_t ci = 0; ci < collection_set->active_regions(); ci++) {
 642       ShenandoahHeapRegion* cs_heap_region = collection_set->get(ci);
 643       size_t cs_heap_region_number = cs_heap_region->region_number();
 644       for (size_t i = 0; i < num; i++) {
 645         if (connections[i * num + cs_heap_region_number] > 0) {
 646           ShenandoahHeapRegion* candidate = regions->get(sorted_by_garbage[i].region_number);
 647           if (maybe_add_heap_region(candidate, collection_set)) {
 648             log_develop_trace(gc)
 649               ("Adding region " SIZE_FORMAT " which is pointed to by region " SIZE_FORMAT, i, cs_heap_region_number);
 650           }
 651         }
 652       }
 653     }
 654     _max_live_data = MAX2(_max_live_data, collection_set->live_data());
 655     collection_set->print();
 656   }
 657 
 658   virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
 659     assert(false, "Shouldn't get here");
 660     return false;
 661   }
 662 };
 663 class PartialHeuristics : public AdaptiveHeuristics {
 664 public:
 665   PartialHeuristics() : AdaptiveHeuristics() {
 666     if (FLAG_IS_DEFAULT(ShenandoahAllocationThreshold)) {
 667       FLAG_SET_DEFAULT(ShenandoahAllocationThreshold, 5);
 668     }
 669     FLAG_SET_DEFAULT(UseShenandoahMatrix, true);


< prev index next >