bool ZRelocationSetSelectorGroup::is_disabled() { // Medium pages are disabled when their page size is zero return _page_type == ZPageTypeMedium && _page_size == 0;
}
bool ZRelocationSetSelectorGroup::is_selectable() { // Large pages are not selectable return _page_type != ZPageTypeLarge;
}
void ZRelocationSetSelectorGroup::semi_sort() { // Semi-sort live pages by number of live bytes in ascending order const size_t npartitions_shift = 11; const size_t npartitions = (size_t)1 << npartitions_shift; const size_t partition_size = _page_size >> npartitions_shift; const size_t partition_size_shift = exact_log2(partition_size);
// Partition slots/fingers
int partitions[npartitions] = { /* zero initialize */ };
// Calculate partition slots
ZArrayIterator<ZPage*> iter1(&_live_pages);
for (ZPage* page; iter1.next(&page);) { const size_t index = page->live_bytes() >> partition_size_shift;
partitions[index]++;
}
// Calculate partition fingers
int finger = 0;
for (size_t i = 0; i < npartitions; i++) { const int slots = partitions[i];
partitions[i] = finger;
finger += slots;
}
// Sort pages into partitions
ZArrayIterator<ZPage*> iter2(&_live_pages);
for (ZPage* page; iter2.next(&page);) { const size_t index = page->live_bytes() >> partition_size_shift; const int finger = partitions[index]++;
assert(sorted_live_pages.at(finger) == NULL, "Invalid finger");
sorted_live_pages.at_put(finger, page);
}
_live_pages.swap(&sorted_live_pages);
}
void ZRelocationSetSelectorGroup::select_inner() { // Calculate the number of pages to relocate by successively including pages in // a candidate relocation set and calculate the maximum space requirement for // their live objects. const int npages = _live_pages.length();
int selected_from = 0;
int selected_to = 0;
size_t selected_live_bytes = 0;
size_t selected_forwarding_entries = 0;
size_t from_live_bytes = 0;
size_t from_forwarding_entries = 0;
semi_sort();
for (int from = 1; from <= npages; from++) { // Add page to the candidate relocation set
ZPage* const page = _live_pages.at(from - 1);
from_live_bytes += page->live_bytes();
from_forwarding_entries += ZForwarding::nentries(page);
// Calculate the maximum number of pages needed by the candidate relocation set. // By subtracting the object size limit from the pages size we get the maximum // number of pages that the relocation set is guaranteed to fit in, regardless // of in which order the objects are relocated. const int to = ceil((double)(from_live_bytes) / (double)(_page_size - _object_size_limit));
// Calculate the relative difference in reclaimable space compared to our // currently selected final relocation set. If this number is larger than the // acceptable fragmentation limit, then the current candidate relocation set // becomes our new final relocation set. const int diff_from = from - selected_from; const int diff_to = to - selected_to; constdouble diff_reclaimable = 100 - percent_of(diff_to, diff_from);
if (diff_reclaimable > ZFragmentationLimit) {
selected_from = from;
selected_to = to;
selected_live_bytes = from_live_bytes;
selected_forwarding_entries = from_forwarding_entries;
}
void ZRelocationSetSelector::select() { // Select pages to relocate. The resulting relocation set will be // sorted such that medium pages comes first, followed by small // pages. Pages within each page group will be semi-sorted by live // bytes in ascending order. Relocating pages in this order allows // us to start reclaiming memory more quickly.
EventZRelocationSet event;
// Select pages from each group
_large.select();
_medium.select();
_small.select();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.