49 _page_type(page_type), 50 _page_size(page_size), 51 _object_size_limit(object_size_limit), 52 _fragmentation_limit(page_size * (ZFragmentationLimit / 100)), 53 _registered_pages(), 54 _sorted_pages(NULL), 55 _nselected(0), 56 _stats() {} 57 58 ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() { 59 FREE_C_HEAP_ARRAY(ZPage*, _sorted_pages); 60 } 61 62 void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) { 63 const uint8_t type = page->type(); 64 const size_t size = page->size(); 65 const size_t live = page->live_bytes(); 66 const size_t garbage = size - live; 67 68 if (garbage > _fragmentation_limit) { 69 _registered_pages.add(page); 70 } 71 72 _stats._npages++; 73 _stats._total += size; 74 _stats._live += live; 75 _stats._garbage += garbage; 76 } 77 78 void ZRelocationSetSelectorGroup::register_garbage_page(ZPage* page) { 79 const size_t size = page->size(); 80 81 _stats._npages++; 82 _stats._total += size; 83 _stats._garbage += size; 84 _stats._empty += size; 85 } 86 87 bool ZRelocationSetSelectorGroup::is_disabled() { 88 // Medium pages are disabled when their page size is zero 89 return _page_type == ZPageTypeMedium && _page_size == 0; 90 } 91 92 bool ZRelocationSetSelectorGroup::is_selectable() { 93 // Large pages are not selectable 94 return _page_type != ZPageTypeLarge; 95 } 96 97 void ZRelocationSetSelectorGroup::semi_sort() { 98 // Semi-sort registered pages by live bytes in ascending order 99 const size_t npartitions_shift = 11; 100 const size_t npartitions = (size_t)1 << npartitions_shift; 101 const size_t partition_size = _page_size >> npartitions_shift; 102 const size_t partition_size_shift = exact_log2(partition_size); 103 const size_t npages = _registered_pages.size(); 104 105 // Partition slots/fingers 106 size_t partitions[npartitions]; 107 108 // Allocate destination array 109 assert(_sorted_pages == NULL, "Already initialized"); 110 _sorted_pages = NEW_C_HEAP_ARRAY(ZPage*, npages, mtGC); 111 debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*))); 112 113 // Calculate partition slots 114 memset(partitions, 0, sizeof(partitions)); 115 ZArrayIterator<ZPage*> iter1(&_registered_pages); 116 for (ZPage* page; iter1.next(&page);) { 117 const size_t index = page->live_bytes() >> partition_size_shift; 118 partitions[index]++; 119 } 120 121 // Calculate partition fingers 122 size_t finger = 0; 123 for (size_t i = 0; i < npartitions; i++) { 124 const size_t slots = partitions[i]; 125 partitions[i] = finger; 126 finger += slots; 127 } 128 129 // Sort pages into partitions 130 ZArrayIterator<ZPage*> iter2(&_registered_pages); 131 for (ZPage* page; iter2.next(&page);) { 132 const size_t index = page->live_bytes() >> partition_size_shift; 133 const size_t finger = partitions[index]++; 134 assert(_sorted_pages[finger] == NULL, "Invalid finger"); 135 _sorted_pages[finger] = page; 136 } 137 } 138 139 void ZRelocationSetSelectorGroup::select_inner() { 140 // Calculate the number of pages to relocate by successively including pages in 141 // a candidate relocation set and calculate the maximum space requirement for 142 // their live objects. 143 const size_t npages = _registered_pages.size(); 144 size_t selected_from = 0; 145 size_t selected_to = 0; 146 size_t from_size = 0; 147 148 semi_sort(); 149 150 for (size_t from = 1; from <= npages; from++) { 151 // Add page to the candidate relocation set 152 from_size += _sorted_pages[from - 1]->live_bytes(); 153 154 // Calculate the maximum number of pages needed by the candidate relocation set. 155 // By subtracting the object size limit from the pages size we get the maximum 156 // number of pages that the relocation set is guaranteed to fit in, regardless 157 // of in which order the objects are relocated. 158 const size_t to = ceil((double)(from_size) / (double)(_page_size - _object_size_limit)); 159 160 // Calculate the relative difference in reclaimable space compared to our 161 // currently selected final relocation set. If this number is larger than the 162 // acceptable fragmentation limit, then the current candidate relocation set 163 // becomes our new final relocation set. | 49 _page_type(page_type), 50 _page_size(page_size), 51 _object_size_limit(object_size_limit), 52 _fragmentation_limit(page_size * (ZFragmentationLimit / 100)), 53 _registered_pages(), 54 _sorted_pages(NULL), 55 _nselected(0), 56 _stats() {} 57 58 ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() { 59 FREE_C_HEAP_ARRAY(ZPage*, _sorted_pages); 60 } 61 62 void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) { 63 const uint8_t type = page->type(); 64 const size_t size = page->size(); 65 const size_t live = page->live_bytes(); 66 const size_t garbage = size - live; 67 68 if (garbage > _fragmentation_limit) { 69 _registered_pages.append(page); 70 } 71 72 _stats._npages++; 73 _stats._total += size; 74 _stats._live += live; 75 _stats._garbage += garbage; 76 } 77 78 void ZRelocationSetSelectorGroup::register_garbage_page(ZPage* page) { 79 const size_t size = page->size(); 80 81 _stats._npages++; 82 _stats._total += size; 83 _stats._garbage += size; 84 _stats._empty += size; 85 } 86 87 bool ZRelocationSetSelectorGroup::is_disabled() { 88 // Medium pages are disabled when their page size is zero 89 return _page_type == ZPageTypeMedium && _page_size == 0; 90 } 91 92 bool ZRelocationSetSelectorGroup::is_selectable() { 93 // Large pages are not selectable 94 return _page_type != ZPageTypeLarge; 95 } 96 97 void ZRelocationSetSelectorGroup::semi_sort() { 98 // Semi-sort registered pages by live bytes in ascending order 99 const size_t npartitions_shift = 11; 100 const size_t npartitions = (size_t)1 << npartitions_shift; 101 const size_t partition_size = _page_size >> npartitions_shift; 102 const size_t partition_size_shift = exact_log2(partition_size); 103 const size_t npages = _registered_pages.length(); 104 105 // Partition slots/fingers 106 size_t partitions[npartitions]; 107 108 // Allocate destination array 109 assert(_sorted_pages == NULL, "Already initialized"); 110 _sorted_pages = NEW_C_HEAP_ARRAY(ZPage*, npages, mtGC); 111 debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*))); 112 113 // Calculate partition slots 114 memset(partitions, 0, sizeof(partitions)); 115 ZArrayIterator<ZPage*> iter1(&_registered_pages); 116 for (ZPage* page; iter1.next(&page);) { 117 const size_t index = page->live_bytes() >> partition_size_shift; 118 partitions[index]++; 119 } 120 121 // Calculate partition fingers 122 size_t finger = 0; 123 for (size_t i = 0; i < npartitions; i++) { 124 const size_t slots = partitions[i]; 125 partitions[i] = finger; 126 finger += slots; 127 } 128 129 // Sort pages into partitions 130 ZArrayIterator<ZPage*> iter2(&_registered_pages); 131 for (ZPage* page; iter2.next(&page);) { 132 const size_t index = page->live_bytes() >> partition_size_shift; 133 const size_t finger = partitions[index]++; 134 assert(_sorted_pages[finger] == NULL, "Invalid finger"); 135 _sorted_pages[finger] = page; 136 } 137 } 138 139 void ZRelocationSetSelectorGroup::select_inner() { 140 // Calculate the number of pages to relocate by successively including pages in 141 // a candidate relocation set and calculate the maximum space requirement for 142 // their live objects. 143 const size_t npages = _registered_pages.length(); 144 size_t selected_from = 0; 145 size_t selected_to = 0; 146 size_t from_size = 0; 147 148 semi_sort(); 149 150 for (size_t from = 1; from <= npages; from++) { 151 // Add page to the candidate relocation set 152 from_size += _sorted_pages[from - 1]->live_bytes(); 153 154 // Calculate the maximum number of pages needed by the candidate relocation set. 155 // By subtracting the object size limit from the pages size we get the maximum 156 // number of pages that the relocation set is guaranteed to fit in, regardless 157 // of in which order the objects are relocated. 158 const size_t to = ceil((double)(from_size) / (double)(_page_size - _object_size_limit)); 159 160 // Calculate the relative difference in reclaimable space compared to our 161 // currently selected final relocation set. If this number is larger than the 162 // acceptable fragmentation limit, then the current candidate relocation set 163 // becomes our new final relocation set. |