1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/z/zCPU.inline.hpp"
  26 #include "gc/z/zGlobals.hpp"
  27 #include "gc/z/zHeuristics.hpp"
  28 #include "gc/z/zUtils.inline.hpp"
  29 #include "logging/log.hpp"
  30 #include "runtime/globals.hpp"
  31 #include "runtime/os.hpp"
  32 
  33 void ZHeuristics::set_medium_page_size() {
  34   // Set ZPageSizeMedium so that a medium page occupies at most 3.125% of the
  35   // max heap size. ZPageSizeMedium is initially set to 0, which means medium
  36   // pages are effectively disabled. It is adjusted only if ZPageSizeMedium
  37   // becomes larger than ZPageSizeSmall.
  38   const size_t min = ZGranuleSize;
  39   const size_t max = ZGranuleSize * 16;
  40   const size_t unclamped = MaxHeapSize * 0.03125;
  41   const size_t clamped = MIN2(MAX2(min, unclamped), max);
  42   const size_t size = ZUtils::round_down_power_of_2(clamped);
  43 
  44   if (size > ZPageSizeSmall) {
  45     // Enable medium pages
  46     ZPageSizeMedium             = size;
  47     ZPageSizeMediumShift        = log2_intptr(ZPageSizeMedium);
  48     ZObjectSizeLimitMedium      = ZPageSizeMedium / 8;
  49     ZObjectAlignmentMediumShift = ZPageSizeMediumShift - 13;
  50     ZObjectAlignmentMedium      = 1 << ZObjectAlignmentMediumShift;
  51 
  52     log_info(gc, init)("Medium Page Size: " SIZE_FORMAT "M", ZPageSizeMedium / M);
  53   } else {
  54     log_info(gc, init)("Medium Page Size: N/A");
  55   }
  56 }
  57 
  58 bool ZHeuristics::per_cpu_shared_small_page() {
  59   // Use per-CPU shared small pages only if these pages occupy at most 3.125%
  60   // of the max heap size. Otherwise fall back to using a single shared small
  61   // page. This is useful when using small heaps on large machines.
  62   const size_t per_cpu_share = (MaxHeapSize * 0.03125) / ZCPU::count();
  63   return per_cpu_share >= ZPageSizeSmall;
  64 }
  65 
  66 static uint nworkers_based_on_ncpus(double cpu_share_in_percent) {
  67   return ceil(os::initial_active_processor_count() * cpu_share_in_percent / 100.0);
  68 }
  69 
  70 static uint nworkers_based_on_heap_size(double reserve_share_in_percent) {
  71   const int nworkers = (MaxHeapSize * (reserve_share_in_percent / 100.0)) / ZPageSizeSmall;
  72   return MAX2(nworkers, 1);
  73 }
  74 
  75 static uint nworkers(double cpu_share_in_percent) {
  76   // Cap number of workers so that we don't use more than 2% of the max heap
  77   // for the small page reserve. This is useful when using small heaps on
  78   // large machines.
  79   return MIN2(nworkers_based_on_ncpus(cpu_share_in_percent),
  80               nworkers_based_on_heap_size(2.0));
  81 }
  82 
  83 uint ZHeuristics::nparallel_workers() {
  84   // Use 60% of the CPUs, rounded up. We would like to use as many threads as
  85   // possible to increase parallelism. However, using a thread count that is
  86   // close to the number of processors tends to lead to over-provisioning and
  87   // scheduling latency issues. Using 60% of the active processors appears to
  88   // be a fairly good balance.
  89   return nworkers(60.0);
  90 }
  91 
  92 uint ZHeuristics::nconcurrent_workers() {
  93   // Use 12.5% of the CPUs, rounded up. The number of concurrent threads we
  94   // would like to use heavily depends on the type of workload we are running.
  95   // Using too many threads will have a negative impact on the application
  96   // throughput, while using too few threads will prolong the GC-cycle and
  97   // we then risk being out-run by the application. Using 12.5% of the active
  98   // processors appears to be a fairly good balance.
  99   return nworkers(12.5);
 100 }