/* * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
void G1NUMA::initialize_without_numa() { // If NUMA is not enabled or supported, initialize as having a single node.
_num_active_node_ids = 1;
_node_ids = NEW_C_HEAP_ARRAY(int, _num_active_node_ids, mtGC);
_node_ids[0] = 0; // Map index 0 to node 0
_len_node_id_to_index_map = 1;
_node_id_to_index_map = NEW_C_HEAP_ARRAY(uint, _len_node_id_to_index_map, mtGC);
_node_id_to_index_map[0] = 0;
}
void G1NUMA::initialize(bool use_numa) { if (!use_numa) {
initialize_without_numa(); return;
}
uint G1NUMA::preferred_node_index_for_index(uint region_index) const { if (region_size() >= page_size()) { // Simple case, pages are smaller than the region so we // can just alternate over the nodes. return region_index % _num_active_node_ids;
} else { // Multiple regions in one page, so we need to make sure the // regions within a page is preferred on the same node.
size_t regions_per_page = page_size() / region_size(); return (region_index / regions_per_page) % _num_active_node_ids;
}
}
int G1NUMA::numa_id(int index) const {
assert(index < _len_node_id_to_index_map, "Index %d out of range: [0,%d)",
index, _len_node_id_to_index_map); return _node_ids[index];
}
if (AlwaysPreTouch) { // If we already pretouched, we can check actual node index here. // However, if node index is still unknown, use preferred node index.
uint node_index = index_of_address(hr->bottom()); if (node_index != UnknownNodeIndex) { return node_index;
}
}
// Request to spread the given memory evenly across the available NUMA // nodes. Which node to request for a given address is given by the // region size and the page size. Below are two examples on 4 NUMA nodes system: // 1. G1HeapRegionSize(_region_size) is larger than or equal to page size. // * Page #: |-0--||-1--||-2--||-3--||-4--||-5--||-6--||-7--||-8--||-9--||-10-||-11-||-12-||-13-||-14-||-15-| // * HeapRegion #: |----#0----||----#1----||----#2----||----#3----||----#4----||----#5----||----#6----||----#7----| // * NUMA node #: |----#0----||----#1----||----#2----||----#3----||----#0----||----#1----||----#2----||----#3----| // 2. G1HeapRegionSize(_region_size) is smaller than page size. // Memory will be touched one page at a time because G1RegionToSpaceMapper commits // pages one by one. // * Page #: |-----0----||-----1----||-----2----||-----3----||-----4----||-----5----||-----6----||-----7----| // * HeapRegion #: |-#0-||-#1-||-#2-||-#3-||-#4-||-#5-||-#6-||-#7-||-#8-||-#9-||#10-||#11-||#12-||#13-||#14-||#15-| // * NUMA node #: |----#0----||----#1----||----#2----||----#3----||----#0----||----#1----||----#2----||----#3----| void G1NUMA::request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index) { if (!is_enabled()) { return;
}
assert(is_aligned(aligned_address, page_size()), "Given address (" PTR_FORMAT ") should be aligned.", p2i(aligned_address));
assert(is_aligned(size_in_bytes, page_size()), "Given size (" SIZE_FORMAT ") should be aligned.", size_in_bytes);
log_trace(gc, heap, numa)("Request memory [" PTR_FORMAT ", " PTR_FORMAT ") to be NUMA id (%d)",
p2i(aligned_address), p2i((char*)aligned_address + size_in_bytes), _node_ids[node_index]);
os::numa_make_local((char*)aligned_address, size_in_bytes, _node_ids[node_index]);
}
uint G1NUMA::max_search_depth() const { // Multiple of 3 is just random number to limit iterations. // There would be some cases that 1 page may be consisted of multiple HeapRegions. return 3 * MAX2((uint)(page_size() / region_size()), (uint)1) * num_active_nodes();
}
bool G1NodeIndexCheckClosure::do_heap_region(HeapRegion* hr) { // Preferred node index will only have valid node index.
uint preferred_node_index = _numa->preferred_node_index_for_index(hr->hrm_index()); // Active node index may have UnknownNodeIndex.
uint active_node_index = _numa->index_of_address(hr->bottom());
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.