86 finger += slots;
87 }
88
89 // Sort pages into partitions
90 ZArrayIterator<ZPage*> iter2(&_registered_pages);
91 for (ZPage* page; iter2.next(&page);) {
92 const size_t index = page->live_bytes() >> partition_size_shift;
93 const size_t finger = partitions[index]++;
94 assert(_sorted_pages[finger] == NULL, "Invalid finger");
95 _sorted_pages[finger] = page;
96 }
97 }
98
99 void ZRelocationSetSelectorGroup::select() {
100 // Calculate the number of pages to relocate by successively including pages in
101 // a candidate relocation set and calculate the maximum space requirement for
102 // their live objects.
103 const size_t npages = _registered_pages.size();
104 size_t selected_from = 0;
105 size_t selected_to = 0;
106 size_t from_size = 0;
107
108 semi_sort();
109
110 for (size_t from = 1; from <= npages; from++) {
111 // Add page to the candidate relocation set
112 from_size += _sorted_pages[from - 1]->live_bytes();
113
114 // Calculate the maximum number of pages needed by the candidate relocation set.
115 // By subtracting the object size limit from the pages size we get the maximum
116 // number of pages that the relocation set is guaranteed to fit in, regardless
117 // of in which order the objects are relocated.
118 const size_t to = ceil((double)(from_size) / (double)(_page_size - _object_size_limit));
119
120 // Calculate the relative difference in reclaimable space compared to our
121 // currently selected final relocation set. If this number is larger than the
122 // acceptable fragmentation limit, then the current candidate relocation set
123 // becomes our new final relocation set.
124 const size_t diff_from = from - selected_from;
125 const size_t diff_to = to - selected_to;
126 const double diff_reclaimable = 100 - percent_of(diff_to, diff_from);
127 if (diff_reclaimable > ZFragmentationLimit) {
128 selected_from = from;
129 selected_to = to;
130 }
131
132 log_trace(gc, reloc)("Candidate Relocation Set (%s Pages): "
133 SIZE_FORMAT "->" SIZE_FORMAT ", %.1f%% relative defragmentation, %s",
134 _name, from, to, diff_reclaimable, (selected_from == from) ? "Selected" : "Rejected");
135 }
136
137 // Finalize selection
138 _nselected = selected_from;
139
140 // Update statistics
141 _relocating = from_size;
142 for (size_t i = _nselected; i < npages; i++) {
143 ZPage* const page = _sorted_pages[i];
144 _fragmentation += page->size() - page->live_bytes();
145 }
146
147 log_debug(gc, reloc)("Relocation Set (%s Pages): " SIZE_FORMAT "->" SIZE_FORMAT ", " SIZE_FORMAT " skipped",
148 _name, selected_from, selected_to, npages - _nselected);
149 }
150
151 ZPage* const* ZRelocationSetSelectorGroup::selected() const {
152 return _sorted_pages;
153 }
154
155 size_t ZRelocationSetSelectorGroup::nselected() const {
156 return _nselected;
157 }
158
159 size_t ZRelocationSetSelectorGroup::relocating() const {
160 return _relocating;
161 }
|
86 finger += slots;
87 }
88
89 // Sort pages into partitions
90 ZArrayIterator<ZPage*> iter2(&_registered_pages);
91 for (ZPage* page; iter2.next(&page);) {
92 const size_t index = page->live_bytes() >> partition_size_shift;
93 const size_t finger = partitions[index]++;
94 assert(_sorted_pages[finger] == NULL, "Invalid finger");
95 _sorted_pages[finger] = page;
96 }
97 }
98
99 void ZRelocationSetSelectorGroup::select() {
100 // Calculate the number of pages to relocate by successively including pages in
101 // a candidate relocation set and calculate the maximum space requirement for
102 // their live objects.
103 const size_t npages = _registered_pages.size();
104 size_t selected_from = 0;
105 size_t selected_to = 0;
106 size_t selected_from_size = 0;
107 size_t from_size = 0;
108
109 semi_sort();
110
111 for (size_t from = 1; from <= npages; from++) {
112 // Add page to the candidate relocation set
113 from_size += _sorted_pages[from - 1]->live_bytes();
114
115 // Calculate the maximum number of pages needed by the candidate relocation set.
116 // By subtracting the object size limit from the pages size we get the maximum
117 // number of pages that the relocation set is guaranteed to fit in, regardless
118 // of in which order the objects are relocated.
119 const size_t to = ceil((double)(from_size) / (double)(_page_size - _object_size_limit));
120
121 // Calculate the relative difference in reclaimable space compared to our
122 // currently selected final relocation set. If this number is larger than the
123 // acceptable fragmentation limit, then the current candidate relocation set
124 // becomes our new final relocation set.
125 const size_t diff_from = from - selected_from;
126 const size_t diff_to = to - selected_to;
127 const double diff_reclaimable = 100 - percent_of(diff_to, diff_from);
128 if (diff_reclaimable > ZFragmentationLimit) {
129 selected_from = from;
130 selected_to = to;
131 selected_from_size = from_size;
132 }
133
134 log_trace(gc, reloc)("Candidate Relocation Set (%s Pages): "
135 SIZE_FORMAT "->" SIZE_FORMAT ", %.1f%% relative defragmentation, %s",
136 _name, from, to, diff_reclaimable, (selected_from == from) ? "Selected" : "Rejected");
137 }
138
139 // Finalize selection
140 _nselected = selected_from;
141
142 // Update statistics
143 _relocating = selected_from_size;
144 for (size_t i = _nselected; i < npages; i++) {
145 ZPage* const page = _sorted_pages[i];
146 _fragmentation += page->size() - page->live_bytes();
147 }
148
149 log_debug(gc, reloc)("Relocation Set (%s Pages): " SIZE_FORMAT "->" SIZE_FORMAT ", " SIZE_FORMAT " skipped",
150 _name, selected_from, selected_to, npages - _nselected);
151 }
152
153 ZPage* const* ZRelocationSetSelectorGroup::selected() const {
154 return _sorted_pages;
155 }
156
157 size_t ZRelocationSetSelectorGroup::nselected() const {
158 return _nselected;
159 }
160
161 size_t ZRelocationSetSelectorGroup::relocating() const {
162 return _relocating;
163 }
|