--- old/src/hotspot/share/gc/g1/heapRegionManager.cpp 2019-09-21 06:25:16.717961887 -0700 +++ new/src/hotspot/share/gc/g1/heapRegionManager.cpp 2019-09-21 06:25:16.357961899 -0700 @@ -30,6 +30,7 @@ #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" #include "gc/g1/heterogeneousHeapRegionManager.hpp" +#include "logging/logStream.hpp" #include "memory/allocation.hpp" #include "utilities/bitMap.inline.hpp" @@ -103,6 +104,40 @@ return _available_map.at(region); } +HeapRegion* HeapRegionManager::allocate_free_region(HeapRegionType type, uint requested_node_index) { + G1MemoryNodeManager* mgr = G1MemoryNodeManager::mgr(); + HeapRegion* hr = NULL; + bool from_head = !type.is_young(); + + if (mgr->num_active_nodes() > 1) { + uint valid_node_index = mgr->valid_node_index(requested_node_index); + // Try to allocate with requested node index. + hr = _free_list.remove_region_with_node_index(from_head, valid_node_index, NULL); + } + + if (hr == NULL) { + // If there's a single active node or we did not get a region from our requested node, + // try without requested node index. + hr = _free_list.remove_region(from_head); + } + + if (hr != NULL) { + assert(hr->next() == NULL, "Single region should not have next"); + assert(is_available(hr->hrm_index()), "Must be committed"); + if (G1VerifyNUMAIdOfHeapRegions) { + // Read actual node index via system call. + uint actual_node_index = mgr->index_of_address(hr->bottom()); + if (hr->node_index() != actual_node_index) { + log_debug(gc, heap, numa)("Heap Region (%u) has different node index. " + "actual index=%u, index=%u", + hr->hrm_index(), actual_node_index, hr->node_index()); + } + } + } + + return hr; +} + #ifdef ASSERT bool HeapRegionManager::is_free(HeapRegion* hr) const { return _free_list.contains(hr); @@ -117,28 +152,33 @@ return g1h->new_heap_region(hrm_index, mr); } -void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkGang* pretouch_gang) { +void HeapRegionManager::commit_regions(uint index, size_t num_regions, uint node_index, WorkGang* pretouch_gang) { guarantee(num_regions > 0, "Must commit more than zero regions"); guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions"); _num_committed += (uint)num_regions; - _heap_mapper->commit_regions(index, num_regions, pretouch_gang); + _heap_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); // Also commit auxiliary data - _prev_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang); - _next_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang); + _prev_bitmap_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); + _next_bitmap_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); - _bot_mapper->commit_regions(index, num_regions, pretouch_gang); - _cardtable_mapper->commit_regions(index, num_regions, pretouch_gang); + _bot_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); + _cardtable_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); - _card_counts_mapper->commit_regions(index, num_regions, pretouch_gang); + _card_counts_mapper->commit_regions(index, num_regions, node_index, pretouch_gang); } void HeapRegionManager::uncommit_regions(uint start, size_t num_regions) { guarantee(num_regions >= 1, "Need to specify at least one region to uncommit, tried to uncommit zero regions at %u", start); guarantee(_num_committed >= num_regions, "pre-condition"); + // Reset node index to distinguish with committed regions. + for (uint i = start; i < start + num_regions; i++) { + at(i)->set_node_index(G1MemoryNodeManager::InvalidNodeIndex); + } + // Print before uncommitting. if (G1CollectedHeap::heap()->hr_printer()->is_active()) { for (uint i = start; i < start + num_regions; i++) { @@ -162,9 +202,26 @@ _card_counts_mapper->uncommit_regions(start, num_regions); } -void HeapRegionManager::make_regions_available(uint start, uint num_regions, WorkGang* pretouch_gang) { +static void print_numa_id_of_regions(uint start, uint num_regions) { + LogTarget(Debug, gc, heap, numa) lt; + + if (lt.is_enabled()) { + LogStream ls(lt); + + // Print header + // Below logs are checked by TestG1NUMATouchRegions.java. + ls.print_cr("Numa id of heap regions from %u to %u", start, start + num_regions - 1); + ls.print_cr("Heap Region# : numa id of pages"); + + for (uint i = start; i < start + num_regions; i++) { + ls.print_cr("%6u : %u", i, G1CollectedHeap::heap()->region_at(i)->node_index()); + } + } +} + +void HeapRegionManager::make_regions_available(uint start, uint num_regions, uint node_index, WorkGang* pretouch_gang) { guarantee(num_regions > 0, "No point in calling this for zero regions"); - commit_regions(start, num_regions, pretouch_gang); + commit_regions(start, num_regions, node_index, pretouch_gang); for (uint i = start; i < start + num_regions; i++) { if (_regions.get_by_index(i) == NULL) { HeapRegion* new_hr = new_heap_region(i); @@ -187,6 +244,12 @@ hr->initialize(mr); insert_into_free_list(at(i)); + // Set node index of the heap region after initialization. + hr->set_node_index(G1MemoryNodeManager::mgr()->index_of_address(bottom)); + } + + if (G1PrintNUMAIdOfHeapRegions) { + print_numa_id_of_regions(start, num_regions); } } @@ -208,11 +271,11 @@ return MemoryUsage(0, used_sz, committed_sz, committed_sz); } -uint HeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers) { - return expand_at(0, num_regions, pretouch_workers); +uint HeapRegionManager::expand_by(uint num_regions, uint node_index, WorkGang* pretouch_workers) { + return expand_at(0, num_regions, node_index, pretouch_workers); } -uint HeapRegionManager::expand_at(uint start, uint num_regions, WorkGang* pretouch_workers) { +uint HeapRegionManager::expand_at(uint start, uint num_regions, uint node_index, WorkGang* pretouch_workers) { if (num_regions == 0) { return 0; } @@ -226,7 +289,7 @@ while (expanded < num_regions && (num_last_found = find_unavailable_from_idx(cur, &idx_last_found)) > 0) { uint to_expand = MIN2(num_regions - expanded, num_last_found); - make_regions_available(idx_last_found, to_expand, pretouch_workers); + make_regions_available(idx_last_found, to_expand, node_index, pretouch_workers); expanded += to_expand; cur = idx_last_found + num_last_found + 1; } @@ -331,7 +394,7 @@ while (true) { HeapRegion *hr = _regions.get_by_index(curr); if (hr == NULL || !is_available(curr)) { - uint res = expand_at(curr, 1, NULL); + uint res = expand_at(curr, 1, G1MemoryNodeManager::AnyNodeIndex, NULL); if (res == 1) { *expanded = true; return curr; @@ -359,7 +422,7 @@ for (uint curr_index = start_index; curr_index <= last_index; curr_index++) { if (!is_available(curr_index)) { commits++; - expand_at(curr_index, 1, pretouch_workers); + expand_at(curr_index, 1, G1MemoryNodeManager::AnyNodeIndex, pretouch_workers); } HeapRegion* curr_region = _regions.get_by_index(curr_index); if (!curr_region->is_free()) {