diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DefaultResourceCalculator.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DefaultResourceCalculator.java index ab6d7f57483..9a3f7037ee7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DefaultResourceCalculator.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DefaultResourceCalculator.java @@ -57,7 +57,7 @@ public boolean isInvalidDivisor(Resource r) { @Override public float ratio(Resource a, Resource b) { - return (float)a.getMemorySize() / b.getMemorySize(); + return divideSafelyAsFloat(a.getMemorySize(), b.getMemorySize()); } @Override diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DominantResourceCalculator.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DominantResourceCalculator.java index 9aeb51cc2cc..29d7e7ed3b3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DominantResourceCalculator.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/DominantResourceCalculator.java @@ -379,8 +379,8 @@ public float ratio(Resource a, Resource b) { for (int i = 0; i < maxLength; i++) { ResourceInformation aResourceInformation = a.getResourceInformation(i); ResourceInformation bResourceInformation = b.getResourceInformation(i); - float tmp = (float) aResourceInformation.getValue() - / (float) bResourceInformation.getValue(); + final float tmp = divideSafelyAsFloat(aResourceInformation.getValue(), + bResourceInformation.getValue()); ratio = ratio > tmp ? ratio : tmp; } return ratio; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceCalculator.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceCalculator.java index 27394f73a7a..09d5ec18a81 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceCalculator.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceCalculator.java @@ -87,6 +87,24 @@ public static long divideAndCeil(long a, float b) { return (long) Math.ceil(a/b); } + /** + * Divides lhs by rhs. + * If both lhs and rhs are having a value of 0, then we return 0. + * This is to avoid division by zero and return NaN as a result. + * If lhs is zero but rhs is not, Float.infinity will be returned + * as the result. + * @param lhs + * @param rhs + * @return + */ + public static float divideSafelyAsFloat(long lhs, long rhs) { + if (lhs == 0 && rhs == 0) { + return 0; + } else { + return (float) lhs / (float) rhs; + } + } + public static int roundUp(int a, int b) { return divideAndCeil(a, b) * b; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceCalculator.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceCalculator.java index 5f3ed196048..bf04557ebbe 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceCalculator.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceCalculator.java @@ -36,11 +36,11 @@ public class TestResourceCalculator { private final ResourceCalculator resourceCalculator; - @Parameterized.Parameters - public static Collection getParameters() { - return Arrays.asList(new ResourceCalculator[][] { - { new DefaultResourceCalculator() }, - { new DominantResourceCalculator() } }); + @Parameterized.Parameters(name = "{0}") + public static Collection getParameters() { + return Arrays.asList(new Object[][] { + { "DefaultResourceCalculator", new DefaultResourceCalculator() }, + { "DominantResourceCalculator", new DominantResourceCalculator() } }); } @Before @@ -57,7 +57,7 @@ private static void setupExtraResource() { ResourceUtils.resetResourceTypes(conf); } - public TestResourceCalculator(ResourceCalculator rs) { + public TestResourceCalculator(String name, ResourceCalculator rs) { this.resourceCalculator = rs; } @@ -392,4 +392,18 @@ public void testNormalize() { assertEquals(2, result.getVirtualCores()); } } + + @Test + public void testDivisionByZeroRatioDenominatorIsZero() { + float ratio = resourceCalculator.ratio(newResource(1, 1), newResource(0, + 0)); + assertEquals(Float.POSITIVE_INFINITY, ratio, 0.00001); + } + + @Test + public void testDivisionByZeroRatioNumeratorAndDenominatorIsZero() { + float ratio = resourceCalculator.ratio(newResource(0, 0), newResource(0, + 0)); + assertEquals(0.0, ratio, 0.00001); + } } \ No newline at end of file