diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/FairSharePolicy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/FairSharePolicy.java index c3ec47a..57f4300 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/FairSharePolicy.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/FairSharePolicy.java @@ -75,31 +75,68 @@ public String getName() { private static class FairShareComparator implements Comparator, Serializable { private static final long serialVersionUID = 5564969375856699313L; - private static final Resource ONE = Resources.createResource(1); @Override public int compare(Schedulable s1, Schedulable s2) { - double minShareRatio1, minShareRatio2; - double useToWeightRatio1, useToWeightRatio2; - double weight1, weight2; - //Do not repeat the getResourceUsage calculation + // Pre-compute resource usages to avoid duplicate calculation Resource resourceUsage1 = s1.getResourceUsage(); Resource resourceUsage2 = s2.getResourceUsage(); - Resource minShare1 = Resources.min(RESOURCE_CALCULATOR, null, - s1.getMinShare(), s1.getDemand()); - Resource minShare2 = Resources.min(RESOURCE_CALCULATOR, null, - s2.getMinShare(), s2.getDemand()); - boolean s1Needy = Resources.lessThan(RESOURCE_CALCULATOR, null, - resourceUsage1, minShare1); - boolean s2Needy = Resources.lessThan(RESOURCE_CALCULATOR, null, - resourceUsage2, minShare2); - minShareRatio1 = (double) resourceUsage1.getMemorySize() - / Resources.max(RESOURCE_CALCULATOR, null, minShare1, ONE).getMemorySize(); - minShareRatio2 = (double) resourceUsage2.getMemorySize() - / Resources.max(RESOURCE_CALCULATOR, null, minShare2, ONE).getMemorySize(); - - weight1 = s1.getWeights().getWeight(ResourceType.MEMORY); - weight2 = s2.getWeights().getWeight(ResourceType.MEMORY); + + int res = compareMinShareUsage(s1, s2, resourceUsage1, resourceUsage2); + + if (res == 0) { + res = compareFairShareUsage(s1, s2, resourceUsage1, resourceUsage2); + } + + if (res == 0) { + // Apps are tied in fairness ratio. Break the tie by submit time and job + // name to get a deterministic ordering, which is useful for unit tests. + res = (int) Math.signum(s1.getStartTime() - s2.getStartTime()); + if (res == 0) { + res = s1.getName().compareTo(s2.getName()); + } + } + + return res; + } + + private int compareMinShareUsage(Schedulable s1, Schedulable s2, + Resource resourceUsage1, Resource resourceUsage2) { + int res; + Resource minShare1 = Resources + .min(RESOURCE_CALCULATOR, null, s1.getMinShare(), s1.getDemand()); + Resource minShare2 = Resources + .min(RESOURCE_CALCULATOR, null, s2.getMinShare(), s2.getDemand()); + boolean s1Needy = Resources + .lessThan(RESOURCE_CALCULATOR, null, resourceUsage1, minShare1); + boolean s2Needy = Resources + .lessThan(RESOURCE_CALCULATOR, null, resourceUsage2, minShare2); + + if (s1Needy && !s2Needy) { + res = -1; + } else if (s2Needy && !s1Needy) { + res = 1; + } else if (s1Needy && s2Needy) { + double minShareRatio1 = (double) resourceUsage1.getMemorySize() / + Math.max(minShare1.getMemorySize(), 1); + double minShareRatio2 = (double) resourceUsage2.getMemorySize() / + Math.max(minShare2.getMemorySize(), 1); + res = (int) Math.signum(minShareRatio1 - minShareRatio2); + } else { + res = 0; + } + return res; + } + + /** + * To simplify computation, use weights instead of fair shares to calculate + * fair share usage. + */ + private int compareFairShareUsage(Schedulable s1, Schedulable s2, + Resource resourceUsage1, Resource resourceUsage2) { + double weight1 = s1.getWeights().getWeight(ResourceType.MEMORY); + double weight2 = s2.getWeights().getWeight(ResourceType.MEMORY); + double useToWeightRatio1, useToWeightRatio2; if (weight1 > 0.0 && weight2 > 0.0) { useToWeightRatio1 = resourceUsage1.getMemorySize() / weight1; useToWeightRatio2 = resourceUsage2.getMemorySize() / weight2; @@ -116,26 +153,7 @@ public int compare(Schedulable s1, Schedulable s2) { useToWeightRatio2 = -weight2; } } - - int res = 0; - if (s1Needy && !s2Needy) - res = -1; - else if (s2Needy && !s1Needy) - res = 1; - else if (s1Needy && s2Needy) - res = (int) Math.signum(minShareRatio1 - minShareRatio2); - else - // Neither schedulable is needy - res = (int) Math.signum(useToWeightRatio1 - useToWeightRatio2); - if (res == 0) { - // Apps are tied in fairness ratio. Break the tie by submit time and job - // name to get a deterministic ordering, which is useful for unit tests. - res = (int) Math.signum(s1.getStartTime() - s2.getStartTime()); - if (res == 0) { - res = s1.getName().compareTo(s2.getName()); - } - } - return res; + return (int) Math.signum(useToWeightRatio1 - useToWeightRatio2); } }