--- /dev/null 2019-09-04 10:58:08.784555846 -0700 +++ new/src/hotspot/share/gc/g1/g1NUMA.cpp 2019-09-21 06:25:34.541961266 -0700 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2019, 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1NUMA.inline.hpp" +#include "gc/g1/heapRegion.hpp" + +G1NUMA* G1NUMA::_inst = NULL; + +void G1NUMA::init_numa_id_to_index_map(const int* numa_ids, uint num_numa_ids) { + int max_numa_id = 0; + for (uint i = 0; i < num_numa_ids; i++) { + if (numa_ids[i] > max_numa_id) { + max_numa_id = numa_ids[i]; + } + } + + _len_numa_id_to_index_map = max_numa_id + 1; + _numa_id_to_index_map = NEW_C_HEAP_ARRAY(uint, _len_numa_id_to_index_map, mtGC); + // Set all indices with invalid numa id. + memset(_numa_id_to_index_map, + G1MemoryNodeManager::InvalidNodeIndex, + sizeof(uint) * _len_numa_id_to_index_map); + + // Set the indices for the actually retrieved numa ids. + for (uint i = 0; i < num_numa_ids; i++) { + int numa_id = numa_ids[i]; + guarantee(is_valid_numa_id(numa_id), "must be representable in map, numa id(%d)", numa_id); + _numa_id_to_index_map[numa_id] = i; + } +} + +void G1NUMA::touch_memory_whole(address aligned_address, size_t size_in_bytes, uint numa_index) { + log_debug(gc, heap, numa)("Touch memory [" PTR_FORMAT ", " PTR_FORMAT ") to be numa id (%d).", + p2i(aligned_address), p2i(aligned_address + size_in_bytes), _numa_ids[numa_index]); + + // If we have preferred numa id, set the whole given area with it. + os::numa_make_local((char*)aligned_address, size_in_bytes, _numa_ids[numa_index]); +} + +void G1NUMA::touch_memory_roundrobin(address aligned_address, size_t size_in_bytes) { + // If we don't have preferred numa id, touch the given area with round-robin manner. + size_t chunk_size; + if (HeapRegion::GrainBytes >= _page_size) { + chunk_size = HeapRegion::GrainBytes; + } else { + chunk_size = _page_size; + } + + assert(is_aligned(size_in_bytes, chunk_size), "Size to touch " SIZE_FORMAT " should be aligned to " SIZE_FORMAT, + size_in_bytes, chunk_size); + + address start_addr = aligned_address; + address end_addr = aligned_address + size_in_bytes; + + log_debug(gc, heap, numa)("Start touch memory [" PTR_FORMAT ", " PTR_FORMAT + "), chunk_size=" SIZE_FORMAT " with round-robin manner.", + p2i(start_addr), p2i(end_addr), chunk_size); + + do { + uint numa_index = next_numa_index(); + + log_trace(gc, heap, numa)("Touch memory [" PTR_FORMAT ", " PTR_FORMAT ") to be numa id (%d).", + p2i(start_addr), p2i(start_addr + chunk_size), _numa_ids[numa_index]); + os::numa_make_local((char*)start_addr, chunk_size, _numa_ids[numa_index]); + + start_addr += chunk_size; + } while (start_addr < end_addr); +} + +void G1NUMA::touch_memory(address aligned_address, size_t size_in_bytes, uint numa_index) { + if (size_in_bytes == 0) { + return; + } + + if (is_valid_numa_index(numa_index)) { + touch_memory_whole(aligned_address, size_in_bytes, numa_index); + } else { + touch_memory_roundrobin(aligned_address, size_in_bytes); + } +} + +bool G1NUMA::initialize() { + assert(UseNUMA, "Invariant"); + + size_t num_numa_ids = os::numa_get_groups_num(); + + _numa_ids = NEW_C_HEAP_ARRAY(int, num_numa_ids, mtGC); + _num_active_numa_ids = (uint)os::numa_get_leaf_groups(_numa_ids, num_numa_ids); + + // To start from 0 at the first call of next_numa_index(), set to the greatest one. + _next_numa_index = _num_active_numa_ids - 1; + + init_numa_id_to_index_map(_numa_ids, _num_active_numa_ids); + + return true; +} + +void G1NUMA::set_page_size(size_t page_size) { + _page_size = page_size; +} + +G1NUMA::~G1NUMA() { + FREE_C_HEAP_ARRAY(int, _numa_id_to_index_map); + FREE_C_HEAP_ARRAY(int, _numa_ids); +} + +uint G1NUMA::index_of_address(HeapWord* addr) const { + int numa_id = os::numa_get_address_id((uintptr_t)addr); + + return index_of_numa_id(numa_id); +}