src/hotspot/share/gc/g1/g1NUMA.cpp
changeset 59062 6530de931b8e
parent 59060 fce1fa1bdc91
equal deleted inserted replaced
59061:df6f2350edfa 59062:6530de931b8e
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "gc/g1/g1NUMA.hpp"
    26 #include "gc/g1/g1NUMA.hpp"
    27 #include "gc/g1/heapRegion.hpp"
    27 #include "logging/logStream.hpp"
    28 #include "logging/log.hpp"
       
    29 #include "runtime/globals.hpp"
    28 #include "runtime/globals.hpp"
    30 #include "runtime/os.hpp"
    29 #include "runtime/os.hpp"
    31 
    30 
    32 G1NUMA* G1NUMA::_inst = NULL;
    31 G1NUMA* G1NUMA::_inst = NULL;
    33 
    32 
    72 }
    71 }
    73 
    72 
    74 G1NUMA::G1NUMA() :
    73 G1NUMA::G1NUMA() :
    75   _node_id_to_index_map(NULL), _len_node_id_to_index_map(0),
    74   _node_id_to_index_map(NULL), _len_node_id_to_index_map(0),
    76   _node_ids(NULL), _num_active_node_ids(0),
    75   _node_ids(NULL), _num_active_node_ids(0),
    77   _region_size(0), _page_size(0) {
    76   _region_size(0), _page_size(0), _stats(NULL) {
    78 }
    77 }
    79 
    78 
    80 void G1NUMA::initialize_without_numa() {
    79 void G1NUMA::initialize_without_numa() {
    81   // If NUMA is not enabled or supported, initialize as having a singel node.
    80   // If NUMA is not enabled or supported, initialize as having a singel node.
    82   _num_active_node_ids = 1;
    81   _num_active_node_ids = 1;
   117 
   116 
   118   // Set the indices for the actually retrieved node ids.
   117   // Set the indices for the actually retrieved node ids.
   119   for (uint i = 0; i < _num_active_node_ids; i++) {
   118   for (uint i = 0; i < _num_active_node_ids; i++) {
   120     _node_id_to_index_map[_node_ids[i]] = i;
   119     _node_id_to_index_map[_node_ids[i]] = i;
   121   }
   120   }
       
   121 
       
   122   _stats = new G1NUMAStats(_node_ids, _num_active_node_ids);
   122 }
   123 }
   123 
   124 
   124 G1NUMA::~G1NUMA() {
   125 G1NUMA::~G1NUMA() {
       
   126   delete _stats;
   125   FREE_C_HEAP_ARRAY(int, _node_id_to_index_map);
   127   FREE_C_HEAP_ARRAY(int, _node_id_to_index_map);
   126   FREE_C_HEAP_ARRAY(int, _node_ids);
   128   FREE_C_HEAP_ARRAY(int, _node_ids);
   127 }
   129 }
   128 
   130 
   129 void G1NUMA::set_region_info(size_t region_size, size_t page_size) {
   131 void G1NUMA::set_region_info(size_t region_size, size_t page_size) {
   213   uint node_index = preferred_node_index_for_index(region_index);
   215   uint node_index = preferred_node_index_for_index(region_index);
   214 
   216 
   215   assert(is_aligned(aligned_address, page_size()), "Given address (" PTR_FORMAT ") should be aligned.", p2i(aligned_address));
   217   assert(is_aligned(aligned_address, page_size()), "Given address (" PTR_FORMAT ") should be aligned.", p2i(aligned_address));
   216   assert(is_aligned(size_in_bytes, page_size()), "Given size (" SIZE_FORMAT ") should be aligned.", size_in_bytes);
   218   assert(is_aligned(size_in_bytes, page_size()), "Given size (" SIZE_FORMAT ") should be aligned.", size_in_bytes);
   217 
   219 
   218   log_debug(gc, heap, numa)("Request memory [" PTR_FORMAT ", " PTR_FORMAT ") to be numa id (%d).",
   220   log_trace(gc, heap, numa)("Request memory [" PTR_FORMAT ", " PTR_FORMAT ") to be NUMA id (%d)",
   219                             p2i(aligned_address), p2i((char*)aligned_address + size_in_bytes), _node_ids[node_index]);
   221                             p2i(aligned_address), p2i((char*)aligned_address + size_in_bytes), _node_ids[node_index]);
   220   os::numa_make_local((char*)aligned_address, size_in_bytes, _node_ids[node_index]);
   222   os::numa_make_local((char*)aligned_address, size_in_bytes, _node_ids[node_index]);
   221 }
   223 }
   222 
   224 
   223 uint G1NUMA::max_search_depth() const {
   225 uint G1NUMA::max_search_depth() const {
   224   // Multiple of 3 is just random number to limit iterations.
   226   // Multiple of 3 is just random number to limit iterations.
   225   // There would be some cases that 1 page may be consisted of multiple HeapRegions.
   227   // There would be some cases that 1 page may be consisted of multiple HeapRegions.
   226   return 3 * MAX2((uint)(page_size() / region_size()), (uint)1) * num_active_nodes();
   228   return 3 * MAX2((uint)(page_size() / region_size()), (uint)1) * num_active_nodes();
   227 }
   229 }
       
   230 
       
   231 void G1NUMA::update_statistics(G1NUMAStats::NodeDataItems phase,
       
   232                                uint requested_node_index,
       
   233                                uint allocated_node_index) {
       
   234   if (_stats == NULL) {
       
   235     return;
       
   236   }
       
   237 
       
   238   uint converted_req_index;
       
   239   if(requested_node_index < _num_active_node_ids) {
       
   240     converted_req_index = requested_node_index;
       
   241   } else {
       
   242     assert(requested_node_index == AnyNodeIndex,
       
   243            "Requested node index %u should be AnyNodeIndex.", requested_node_index);
       
   244     converted_req_index = _num_active_node_ids;
       
   245   }
       
   246   _stats->update(phase, converted_req_index, allocated_node_index);
       
   247 }
       
   248 
       
   249 void G1NUMA::copy_statistics(G1NUMAStats::NodeDataItems phase,
       
   250                              uint requested_node_index,
       
   251                              size_t* allocated_stat) {
       
   252   if (_stats == NULL) {
       
   253     return;
       
   254   }
       
   255 
       
   256   _stats->copy(phase, requested_node_index, allocated_stat);
       
   257 }
       
   258 
       
   259 void G1NUMA::print_statistics() const {
       
   260   if (_stats == NULL) {
       
   261     return;
       
   262   }
       
   263 
       
   264   _stats->print_statistics();
       
   265 }
       
   266 
       
   267 G1NodeIndexCheckClosure::G1NodeIndexCheckClosure(const char* desc, G1NUMA* numa, LogStream* ls) :
       
   268   _desc(desc), _numa(numa), _ls(ls) {
       
   269 
       
   270   uint num_nodes = _numa->num_active_nodes();
       
   271   _matched = NEW_C_HEAP_ARRAY(uint, num_nodes, mtGC);
       
   272   _mismatched = NEW_C_HEAP_ARRAY(uint, num_nodes, mtGC);
       
   273   _total = NEW_C_HEAP_ARRAY(uint, num_nodes, mtGC);
       
   274   memset(_matched, 0, sizeof(uint) * num_nodes);
       
   275   memset(_mismatched, 0, sizeof(uint) * num_nodes);
       
   276   memset(_total, 0, sizeof(uint) * num_nodes);
       
   277 }
       
   278 
       
   279 G1NodeIndexCheckClosure::~G1NodeIndexCheckClosure() {
       
   280   _ls->print("%s: NUMA region verification (id: matched/mismatched/total): ", _desc);
       
   281   const int* numa_ids = _numa->node_ids();
       
   282   for (uint i = 0; i < _numa->num_active_nodes(); i++) {
       
   283     _ls->print("%d: %u/%u/%u ", numa_ids[i], _matched[i], _mismatched[i], _total[i]);
       
   284   }
       
   285 
       
   286   FREE_C_HEAP_ARRAY(uint, _matched);
       
   287   FREE_C_HEAP_ARRAY(uint, _mismatched);
       
   288   FREE_C_HEAP_ARRAY(uint, _total);
       
   289 }
       
   290 
       
   291 bool G1NodeIndexCheckClosure::do_heap_region(HeapRegion* hr) {
       
   292   // Preferred node index will only have valid node index.
       
   293   uint preferred_node_index = _numa->preferred_node_index_for_index(hr->hrm_index());
       
   294   // Active node index may have UnknownNodeIndex.
       
   295   uint active_node_index = _numa->index_of_address(hr->bottom());
       
   296 
       
   297   if (preferred_node_index == active_node_index) {
       
   298     _matched[preferred_node_index]++;
       
   299   } else if (active_node_index != G1NUMA::UnknownNodeIndex) {
       
   300     _mismatched[preferred_node_index]++;
       
   301   }
       
   302   _total[preferred_node_index]++;
       
   303 
       
   304   return false;
       
   305 }