|
@@ -18,35 +18,84 @@
|
|
|
|
|
|
package org.apache.hadoop.yarn.server.nodemanager.util;
|
|
|
|
|
|
+import org.apache.commons.logging.Log;
|
|
|
+import org.apache.commons.logging.LogFactory;
|
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
import org.apache.hadoop.classification.InterfaceStability;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
|
import org.apache.hadoop.yarn.util.ResourceCalculatorPlugin;
|
|
|
|
|
|
+/**
|
|
|
+ * Helper class to determine hardware related characteristics such as the
|
|
|
+ * number of processors and the amount of memory on the node.
|
|
|
+ */
|
|
|
@InterfaceAudience.Private
|
|
|
@InterfaceStability.Unstable
|
|
|
public class NodeManagerHardwareUtils {
|
|
|
|
|
|
+ private static final Log LOG = LogFactory
|
|
|
+ .getLog(NodeManagerHardwareUtils.class);
|
|
|
+
|
|
|
/**
|
|
|
*
|
|
|
- * Returns the fraction of CPU cores that should be used for YARN containers.
|
|
|
+ * Returns the number of CPUs on the node. This value depends on the
|
|
|
+ * configuration setting which decides whether to count logical processors
|
|
|
+ * (such as hyperthreads) as cores or not.
|
|
|
+ *
|
|
|
+ * @param conf
|
|
|
+ * - Configuration object
|
|
|
+ * @return Number of CPUs
|
|
|
+ */
|
|
|
+ public static int getNodeCPUs(Configuration conf) {
|
|
|
+ ResourceCalculatorPlugin plugin =
|
|
|
+ ResourceCalculatorPlugin.getResourceCalculatorPlugin(null, conf);
|
|
|
+ return NodeManagerHardwareUtils.getNodeCPUs(plugin, conf);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * Returns the number of CPUs on the node. This value depends on the
|
|
|
+ * configuration setting which decides whether to count logical processors
|
|
|
+ * (such as hyperthreads) as cores or not.
|
|
|
+ *
|
|
|
+ * @param plugin
|
|
|
+ * - ResourceCalculatorPlugin object to determine hardware specs
|
|
|
+ * @param conf
|
|
|
+ * - Configuration object
|
|
|
+ * @return Number of CPU cores on the node.
|
|
|
+ */
|
|
|
+ public static int getNodeCPUs(ResourceCalculatorPlugin plugin,
|
|
|
+ Configuration conf) {
|
|
|
+ int numProcessors = plugin.getNumProcessors();
|
|
|
+ boolean countLogicalCores =
|
|
|
+ conf.getBoolean(YarnConfiguration.NM_COUNT_LOGICAL_PROCESSORS_AS_CORES,
|
|
|
+ YarnConfiguration.DEFAULT_NM_COUNT_LOGICAL_PROCESSORS_AS_CORES);
|
|
|
+ if (!countLogicalCores) {
|
|
|
+ numProcessors = plugin.getNumCores();
|
|
|
+ }
|
|
|
+ return numProcessors;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * Returns the fraction of CPUs that should be used for YARN containers.
|
|
|
* The number is derived based on various configuration params such as
|
|
|
* YarnConfiguration.NM_RESOURCE_PERCENTAGE_PHYSICAL_CPU_LIMIT
|
|
|
*
|
|
|
* @param conf
|
|
|
* - Configuration object
|
|
|
- * @return Fraction of CPU cores to be used for YARN containers
|
|
|
+ * @return Fraction of CPUs to be used for YARN containers
|
|
|
*/
|
|
|
- public static float getContainersCores(Configuration conf) {
|
|
|
+ public static float getContainersCPUs(Configuration conf) {
|
|
|
ResourceCalculatorPlugin plugin =
|
|
|
ResourceCalculatorPlugin.getResourceCalculatorPlugin(null, conf);
|
|
|
- return NodeManagerHardwareUtils.getContainersCores(plugin, conf);
|
|
|
+ return NodeManagerHardwareUtils.getContainersCPUs(plugin, conf);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
- * Returns the fraction of CPU cores that should be used for YARN containers.
|
|
|
+ * Returns the fraction of CPUs that should be used for YARN containers.
|
|
|
* The number is derived based on various configuration params such as
|
|
|
* YarnConfiguration.NM_RESOURCE_PERCENTAGE_PHYSICAL_CPU_LIMIT
|
|
|
*
|
|
@@ -54,11 +103,11 @@ public class NodeManagerHardwareUtils {
|
|
|
* - ResourceCalculatorPlugin object to determine hardware specs
|
|
|
* @param conf
|
|
|
* - Configuration object
|
|
|
- * @return Fraction of CPU cores to be used for YARN containers
|
|
|
+ * @return Fraction of CPUs to be used for YARN containers
|
|
|
*/
|
|
|
- public static float getContainersCores(ResourceCalculatorPlugin plugin,
|
|
|
+ public static float getContainersCPUs(ResourceCalculatorPlugin plugin,
|
|
|
Configuration conf) {
|
|
|
- int numProcessors = plugin.getNumProcessors();
|
|
|
+ int numProcessors = getNodeCPUs(plugin, conf);
|
|
|
int nodeCpuPercentage = getNodeCpuPercentage(conf);
|
|
|
|
|
|
return (nodeCpuPercentage * numProcessors) / 100.0f;
|
|
@@ -88,4 +137,177 @@ public class NodeManagerHardwareUtils {
|
|
|
}
|
|
|
return nodeCpuPercentage;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to return the number of vcores on the system that can be used for
|
|
|
+ * YARN containers. If a number is specified in the configuration file, then
|
|
|
+ * that number is returned. If nothing is specified - 1. If the OS is an
|
|
|
+ * "unknown" OS(one for which we don't have ResourceCalculatorPlugin
|
|
|
+ * implemented), return the default NodeManager cores. 2. If the config
|
|
|
+ * variable yarn.nodemanager.cpu.use_logical_processors is set to true, it
|
|
|
+ * returns the logical processor count(count hyperthreads as cores), else it
|
|
|
+ * returns the physical cores count.
|
|
|
+ *
|
|
|
+ * @param conf
|
|
|
+ * - the configuration for the NodeManager
|
|
|
+ * @return the number of cores to be used for YARN containers
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public static int getVCores(Configuration conf) {
|
|
|
+ // is this os for which we can determine cores?
|
|
|
+ ResourceCalculatorPlugin plugin =
|
|
|
+ ResourceCalculatorPlugin.getResourceCalculatorPlugin(null, conf);
|
|
|
+
|
|
|
+ return NodeManagerHardwareUtils.getVCores(plugin, conf);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to return the number of vcores on the system that can be used for
|
|
|
+ * YARN containers. If a number is specified in the configuration file, then
|
|
|
+ * that number is returned. If nothing is specified - 1. If the OS is an
|
|
|
+ * "unknown" OS(one for which we don't have ResourceCalculatorPlugin
|
|
|
+ * implemented), return the default NodeManager cores. 2. If the config
|
|
|
+ * variable yarn.nodemanager.cpu.use_logical_processors is set to true, it
|
|
|
+ * returns the logical processor count(count hyperthreads as cores), else it
|
|
|
+ * returns the physical cores count.
|
|
|
+ *
|
|
|
+ * @param plugin
|
|
|
+ * - ResourceCalculatorPlugin object to determine hardware specs
|
|
|
+ * @param conf
|
|
|
+ * - the configuration for the NodeManager
|
|
|
+ * @return the number of cores to be used for YARN containers
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public static int getVCores(ResourceCalculatorPlugin plugin,
|
|
|
+ Configuration conf) {
|
|
|
+
|
|
|
+ int cores;
|
|
|
+ boolean hardwareDetectionEnabled =
|
|
|
+ conf.getBoolean(
|
|
|
+ YarnConfiguration.NM_ENABLE_HARDWARE_CAPABILITY_DETECTION,
|
|
|
+ YarnConfiguration.DEFAULT_NM_ENABLE_HARDWARE_CAPABILITY_DETECTION);
|
|
|
+
|
|
|
+ String message;
|
|
|
+ if (!hardwareDetectionEnabled || plugin == null) {
|
|
|
+ cores =
|
|
|
+ conf.getInt(YarnConfiguration.NM_VCORES,
|
|
|
+ YarnConfiguration.DEFAULT_NM_VCORES);
|
|
|
+ if (cores == -1) {
|
|
|
+ cores = YarnConfiguration.DEFAULT_NM_VCORES;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ cores = conf.getInt(YarnConfiguration.NM_VCORES, -1);
|
|
|
+ if (cores == -1) {
|
|
|
+ float physicalCores =
|
|
|
+ NodeManagerHardwareUtils.getContainersCPUs(plugin, conf);
|
|
|
+ float multiplier =
|
|
|
+ conf.getFloat(YarnConfiguration.NM_PCORES_VCORES_MULTIPLIER,
|
|
|
+ YarnConfiguration.DEFAULT_NM_PCORES_VCORES_MULTIPLIER);
|
|
|
+ if (multiplier > 0) {
|
|
|
+ float tmp = physicalCores * multiplier;
|
|
|
+ if (tmp > 0 && tmp < 1) {
|
|
|
+ // on a single core machine - tmp can be between 0 and 1
|
|
|
+ cores = 1;
|
|
|
+ } else {
|
|
|
+ cores = (int) tmp;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ message = "Illegal value for "
|
|
|
+ + YarnConfiguration.NM_PCORES_VCORES_MULTIPLIER
|
|
|
+ + ". Value must be greater than 0.";
|
|
|
+ throw new IllegalArgumentException(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(cores <= 0) {
|
|
|
+ message = "Illegal value for " + YarnConfiguration.NM_VCORES
|
|
|
+ + ". Value must be greater than 0.";
|
|
|
+ throw new IllegalArgumentException(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ return cores;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to return how much memory we should set aside for YARN containers.
|
|
|
+ * If a number is specified in the configuration file, then that number is
|
|
|
+ * returned. If nothing is specified - 1. If the OS is an "unknown" OS(one for
|
|
|
+ * which we don't have ResourceCalculatorPlugin implemented), return the
|
|
|
+ * default NodeManager physical memory. 2. If the OS has a
|
|
|
+ * ResourceCalculatorPlugin implemented, the calculation is 0.8 * (RAM - 2 *
|
|
|
+ * JVM-memory) i.e. use 80% of the memory after accounting for memory used by
|
|
|
+ * the DataNode and the NodeManager. If the number is less than 1GB, log a
|
|
|
+ * warning message.
|
|
|
+ *
|
|
|
+ * @param conf
|
|
|
+ * - the configuration for the NodeManager
|
|
|
+ * @return the amount of memory that will be used for YARN containers in MB.
|
|
|
+ */
|
|
|
+ public static int getContainerMemoryMB(Configuration conf) {
|
|
|
+ return NodeManagerHardwareUtils.getContainerMemoryMB(
|
|
|
+ ResourceCalculatorPlugin.getResourceCalculatorPlugin(null, conf), conf);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to return how much memory we should set aside for YARN containers.
|
|
|
+ * If a number is specified in the configuration file, then that number is
|
|
|
+ * returned. If nothing is specified - 1. If the OS is an "unknown" OS(one for
|
|
|
+ * which we don't have ResourceCalculatorPlugin implemented), return the
|
|
|
+ * default NodeManager physical memory. 2. If the OS has a
|
|
|
+ * ResourceCalculatorPlugin implemented, the calculation is 0.8 * (RAM - 2 *
|
|
|
+ * JVM-memory) i.e. use 80% of the memory after accounting for memory used by
|
|
|
+ * the DataNode and the NodeManager. If the number is less than 1GB, log a
|
|
|
+ * warning message.
|
|
|
+ *
|
|
|
+ * @param plugin
|
|
|
+ * - ResourceCalculatorPlugin object to determine hardware specs
|
|
|
+ * @param conf
|
|
|
+ * - the configuration for the NodeManager
|
|
|
+ * @return the amount of memory that will be used for YARN containers in MB.
|
|
|
+ */
|
|
|
+ public static int getContainerMemoryMB(ResourceCalculatorPlugin plugin,
|
|
|
+ Configuration conf) {
|
|
|
+
|
|
|
+ int memoryMb;
|
|
|
+ boolean hardwareDetectionEnabled = conf.getBoolean(
|
|
|
+ YarnConfiguration.NM_ENABLE_HARDWARE_CAPABILITY_DETECTION,
|
|
|
+ YarnConfiguration.DEFAULT_NM_ENABLE_HARDWARE_CAPABILITY_DETECTION);
|
|
|
+
|
|
|
+ if (!hardwareDetectionEnabled || plugin == null) {
|
|
|
+ memoryMb = conf.getInt(YarnConfiguration.NM_PMEM_MB,
|
|
|
+ YarnConfiguration.DEFAULT_NM_PMEM_MB);
|
|
|
+ if (memoryMb == -1) {
|
|
|
+ memoryMb = YarnConfiguration.DEFAULT_NM_PMEM_MB;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ memoryMb = conf.getInt(YarnConfiguration.NM_PMEM_MB, -1);
|
|
|
+ if (memoryMb == -1) {
|
|
|
+ int physicalMemoryMB =
|
|
|
+ (int) (plugin.getPhysicalMemorySize() / (1024 * 1024));
|
|
|
+ int hadoopHeapSizeMB =
|
|
|
+ (int) (Runtime.getRuntime().maxMemory() / (1024 * 1024));
|
|
|
+ int containerPhysicalMemoryMB =
|
|
|
+ (int) (0.8f * (physicalMemoryMB - (2 * hadoopHeapSizeMB)));
|
|
|
+ int reservedMemoryMB =
|
|
|
+ conf.getInt(YarnConfiguration.NM_SYSTEM_RESERVED_PMEM_MB, -1);
|
|
|
+ if (reservedMemoryMB != -1) {
|
|
|
+ containerPhysicalMemoryMB = physicalMemoryMB - reservedMemoryMB;
|
|
|
+ }
|
|
|
+ if(containerPhysicalMemoryMB <= 0) {
|
|
|
+ LOG.error("Calculated memory for YARN containers is too low."
|
|
|
+ + " Node memory is " + physicalMemoryMB
|
|
|
+ + " MB, system reserved memory is "
|
|
|
+ + reservedMemoryMB + " MB.");
|
|
|
+ }
|
|
|
+ containerPhysicalMemoryMB = Math.max(containerPhysicalMemoryMB, 0);
|
|
|
+ memoryMb = containerPhysicalMemoryMB;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(memoryMb <= 0) {
|
|
|
+ String message = "Illegal value for " + YarnConfiguration.NM_PMEM_MB
|
|
|
+ + ". Value must be greater than 0.";
|
|
|
+ throw new IllegalArgumentException(message);
|
|
|
+ }
|
|
|
+ return memoryMb;
|
|
|
+ }
|
|
|
}
|