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/FSLeafQueue.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSLeafQueue.java index 3b3f6ce..e13d373 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSLeafQueue.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSLeafQueue.java @@ -138,6 +138,11 @@ public void recomputeShares() { } @Override + public void recomputeSteadyShares() { + policy.computeSteadyShares(getRunnableAppSchedulables(), getSteadyFairShare()); + } + + @Override public Resource getDemand() { return demand; } 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/FSParentQueue.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSParentQueue.java index 9af72a5..40251d4 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSParentQueue.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSParentQueue.java @@ -35,7 +35,6 @@ import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer; import org.apache.hadoop.yarn.util.resource.Resources; -import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ActiveUsersManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerApplicationAttempt; @@ -69,6 +68,15 @@ public void recomputeShares() { } @Override + public void recomputeSteadyShares() { + policy.computeSteadyShares(childQueues, getSteadyFairShare()); + for (FSQueue childQueue : childQueues) { + childQueue.getMetrics().setSteadyFairShare(childQueue.getSteadyFairShare()); + childQueue.recomputeSteadyShares(); + } + } + + @Override public Resource getDemand() { return demand; } 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/FSQueue.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueue.java index 1e94046..7baef75 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueue.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueue.java @@ -145,6 +145,12 @@ public void setFairShare(Resource fairShare) { super.setFairShare(fairShare); metrics.setFairShare(fairShare); } + + @Override + public void setSteadyFairShare(Resource steadyFairShare) { + super.setSteadyFairShare(steadyFairShare); + metrics.setSteadyFairShare(steadyFairShare); + } public boolean hasAccess(QueueACL acl, UserGroupInformation user) { return scheduler.getAllocationConfiguration().hasAccess(name, acl, user); @@ -155,7 +161,13 @@ public boolean hasAccess(QueueACL acl, UserGroupInformation user) { * queue's current share */ public abstract void recomputeShares(); - + + /** + * Recomputes the steady shares of all child queues and applications based on + * this queue's current share + */ + public abstract void recomputeSteadyShares(); + /** * Gets the children of this queue, if any. */ 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/FSQueueMetrics.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueueMetrics.java index ff0956e..82c422b 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueueMetrics.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSQueueMetrics.java @@ -33,6 +33,8 @@ @Metric("Fair share of memory in MB") MutableGaugeInt fairShareMB; @Metric("Fair share of CPU in vcores") MutableGaugeInt fairShareVCores; + @Metric("Steady fair share of memory in MB") MutableGaugeInt steadyFairShareMB; + @Metric("Steady fair share of CPU in vcores") MutableGaugeInt steadyFairShareVCores; @Metric("Minimum share of memory in MB") MutableGaugeInt minShareMB; @Metric("Minimum share of CPU in vcores") MutableGaugeInt minShareVCores; @Metric("Maximum share of memory in MB") MutableGaugeInt maxShareMB; @@ -55,7 +57,20 @@ public int getFairShareMB() { public int getFairShareVirtualCores() { return fairShareVCores.value(); } - + + public void setSteadyFairShare(Resource resource) { + steadyFairShareMB.set(resource.getMemory()); + steadyFairShareVCores.set(resource.getVirtualCores()); + } + + public int getSteadyFairShareMB() { + return steadyFairShareMB.value(); + } + + public int getSteadyFairShareVCores() { + return steadyFairShareVCores.value(); + } + public void setMinShare(Resource resource) { minShareMB.set(resource.getMemory()); minShareVCores.set(resource.getVirtualCores()); 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/FairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java index 8765ba0..cb34612 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java @@ -853,6 +853,8 @@ private synchronized void addNode(RMNode node) { Resources.addTo(clusterResource, node.getTotalCapability()); updateRootQueueMetrics(); + queueMgr.getRootQueue().setSteadyFairShare(clusterResource); + queueMgr.getRootQueue().recomputeSteadyShares(); LOG.info("Added node " + node.getNodeAddress() + " cluster capacity: " + clusterResource); } @@ -887,6 +889,8 @@ private synchronized void removeNode(RMNode rmNode) { } nodes.remove(rmNode.getNodeID()); + queueMgr.getRootQueue().setSteadyFairShare(clusterResource); + queueMgr.getRootQueue().recomputeSteadyShares(); LOG.info("Removed node " + rmNode.getNodeAddress() + " cluster capacity: " + clusterResource); } 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/QueueManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java index 4f8735b..c64414d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java @@ -118,6 +118,9 @@ private FSQueue getQueue(String name, boolean create, FSQueueType queueType) { if (queue == null && create) { // if the queue doesn't exist,create it and return queue = createQueue(name, queueType); + + // Update steady fair share for all queues + rootQueue.recomputeSteadyShares(); } return queue; } @@ -190,7 +193,7 @@ private FSQueue createQueue(String name, FSQueueType queueType) { parent = newParent; } } - + return parent; } @@ -376,5 +379,8 @@ public void updateAllocationConfiguration(AllocationConfiguration queueConf) { + queue.getName(), ex); } } + + // Update steady fair shares for all queues + rootQueue.recomputeSteadyShares(); } } 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/Schedulable.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/Schedulable.java index 5134be4..e957d3a 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/Schedulable.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/Schedulable.java @@ -60,6 +60,8 @@ public abstract class Schedulable { /** Fair share assigned to this Schedulable */ private Resource fairShare = Resources.createResource(0); + /** Steady fair share assigned to this Schedulable */ + private Resource steadyFairShare = Resources.createResource(0); /** * Name of job/queue, used for debugging as well as for breaking ties in @@ -116,6 +118,16 @@ public Resource getFairShare() { return fairShare; } + /** Assign a steady fair share to this Schedulable. */ + public void setSteadyFairShare(Resource steadyFairShare) { + this.steadyFairShare = steadyFairShare; + } + + /** Get the steady fair share assigned to this Schedulable. */ + public Resource getSteadyFairShare() { + return steadyFairShare; + } + /** * Returns true if queue has atleast one app running. Always returns true for * AppSchedulables. 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/SchedulingPolicy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/SchedulingPolicy.java index 1087c73..048b342 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/SchedulingPolicy.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/SchedulingPolicy.java @@ -141,6 +141,16 @@ public abstract void computeShares( Collection schedulables, Resource totalResources); /** + * Computes and updates the steady shares of {@link Schedulable}s as per the + * {@link SchedulingPolicy}. + * + * @param schedulables {@link Schedulable}s whose shares are to be updated + * @param totalResources Total {@link Resource}s in the cluster + */ + public abstract void computeSteadyShares( + Collection schedulables, Resource totalResources); + + /** * Check if the resource usage is over the fair share under this policy * * @param usage {@link Resource} the resource usage 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/ComputeFairShares.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/ComputeFairShares.java index 6363ec0..29aad5d 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/ComputeFairShares.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/ComputeFairShares.java @@ -56,7 +56,22 @@ public static void computeShares( } } - computeSharesInternal(activeSchedulables, totalResources, type); + computeSharesInternal(activeSchedulables, totalResources, type, false); + } + + /** + * Compute the steady fair share of the given schedulables. The steady fair + * share is an allocation of shares considering all schedulables, i.e., + * active and inactive. + * + * @param schedulables + * @param totalResources + * @param type + */ + public static void computeSteadyShares( + Collection schedulables, Resource totalResources, + ResourceType type) { + computeSharesInternal(schedulables, totalResources, type, true); } /** @@ -102,7 +117,7 @@ public static void computeShares( */ private static void computeSharesInternal( Collection schedulables, Resource totalResources, - ResourceType type) { + ResourceType type, boolean isSteadyShare) { if (schedulables.isEmpty()) { return; } @@ -145,7 +160,13 @@ private static void computeSharesInternal( } // Set the fair shares based on the value of R we've converged to for (Schedulable sched : schedulables) { - setResourceValue(computeShare(sched, right, type), sched.getFairShare(), type); + if (isSteadyShare) { + setResourceValue( + computeShare(sched, right, type), sched.getSteadyFairShare(), type); + } else { + setResourceValue( + computeShare(sched, right, type), sched.getFairShare(), type); + } } } 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/DominantResourceFairnessPolicy.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/DominantResourceFairnessPolicy.java index af674b9..28842ca 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/DominantResourceFairnessPolicy.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/DominantResourceFairnessPolicy.java @@ -68,6 +68,14 @@ public void computeShares(Collection schedulables, ComputeFairShares.computeShares(schedulables, totalResources, type); } } + + @Override + public void computeSteadyShares(Collection schedulables, + Resource totalResources) { + for (ResourceType type : ResourceType.values()) { + ComputeFairShares.computeSteadyShares(schedulables, totalResources, type); + } + } @Override public boolean checkIfUsageOverFairShare(Resource usage, Resource fairShare) { 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 c51852f..012f3a6 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 @@ -120,6 +120,13 @@ public void computeShares(Collection schedulables, } @Override + public void computeSteadyShares(Collection schedulables, + Resource totalResources) { + ComputeFairShares.computeSteadyShares(schedulables, totalResources, + ResourceType.MEMORY); + } + + @Override public boolean checkIfUsageOverFairShare(Resource usage, Resource fairShare) { return Resources.greaterThan(RESOURCE_CALCULATOR, null, usage, fairShare); } 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/FifoPolicy.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/FifoPolicy.java index 0f43097..39de159 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/FifoPolicy.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/FifoPolicy.java @@ -88,6 +88,23 @@ public void computeShares(Collection schedulables, } @Override + public void computeSteadyShares(Collection schedulables, + Resource totalResources) { + if (schedulables.isEmpty()) { + return; + } + + Schedulable earliest = null; + for (Schedulable schedulable : schedulables) { + if (earliest == null || + schedulable.getStartTime() < earliest.getStartTime()) { + earliest = schedulable; + } + } + earliest.setSteadyFairShare(Resources.clone(totalResources)); + } + + @Override public boolean checkIfUsageOverFairShare(Resource usage, Resource fairShare) { throw new UnsupportedOperationException( "FifoPolicy doesn't support checkIfUsageOverFairshare operation, " + diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestComputeFairShares.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestComputeFairShares.java index 9d8dd07..569abf2 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestComputeFairShares.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestComputeFairShares.java @@ -54,6 +54,9 @@ public void testEqualSharing() { ComputeFairShares.computeShares(scheds, Resources.createResource(40), ResourceType.MEMORY); verifyMemoryShares(10, 10, 10, 10); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(40), ResourceType.MEMORY); + verifyMemorySteadyShares(10, 10, 10, 10); } /** @@ -72,6 +75,9 @@ public void testLowMaxShares() { ComputeFairShares.computeShares(scheds, Resources.createResource(40), ResourceType.MEMORY); verifyMemoryShares(13, 13, 11, 3); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(40), ResourceType.MEMORY); + verifyMemorySteadyShares(13, 13, 11, 3); } @@ -92,6 +98,9 @@ public void testMinShares() { ComputeFairShares.computeShares(scheds, Resources.createResource(40), ResourceType.MEMORY); verifyMemoryShares(20, 18, 0, 2); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(40), ResourceType.MEMORY); + verifyMemorySteadyShares(20, 18, 0, 2); } /** @@ -107,6 +116,9 @@ public void testWeightedSharing() { ComputeFairShares.computeShares(scheds, Resources.createResource(45), ResourceType.MEMORY); verifyMemoryShares(20, 10, 10, 5); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(45), ResourceType.MEMORY); + verifyMemorySteadyShares(20, 10, 10, 5); } /** @@ -125,9 +137,11 @@ public void testWeightedSharingWithMaxShares() { ComputeFairShares.computeShares(scheds, Resources.createResource(45), ResourceType.MEMORY); verifyMemoryShares(10, 11, 16, 8); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(45), ResourceType.MEMORY); + verifyMemorySteadyShares(10, 11, 16, 8); } - /** * Weighted fair sharing test with min shares. As in the min share test above, * pool 1 has a min share greater than its demand so it only gets its demand. @@ -144,6 +158,9 @@ public void testWeightedSharingWithMinShares() { ComputeFairShares.computeShares(scheds, Resources.createResource(45), ResourceType.MEMORY); verifyMemoryShares(20, 5, 5, 15); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(45), ResourceType.MEMORY); + verifyMemorySteadyShares(20, 5, 5, 15); } /** @@ -160,6 +177,10 @@ public void testLargeShares() { ComputeFairShares.computeShares(scheds, Resources.createResource(40 * million), ResourceType.MEMORY); verifyMemoryShares(10 * million, 10 * million, 10 * million, 10 * million); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(40 * million), ResourceType.MEMORY); + verifyMemorySteadyShares(10 * million, 10 * million, 10 * million, + 10 * million); } /** @@ -170,6 +191,9 @@ public void testEmptyList() { ComputeFairShares.computeShares(scheds, Resources.createResource(40), ResourceType.MEMORY); verifyMemoryShares(); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(40), ResourceType.MEMORY); + verifyMemorySteadyShares(); } /** @@ -188,6 +212,9 @@ public void testCPU() { ComputeFairShares.computeShares(scheds, Resources.createResource(0, 45), ResourceType.CPU); verifyCPUShares(20, 5, 5, 15); + ComputeFairShares.computeSteadyShares(scheds, + Resources.createResource(0, 45), ResourceType.CPU); + verifyCPUSteadyShares(20, 5, 5, 15); } /** @@ -199,6 +226,17 @@ private void verifyMemoryShares(int... shares) { Assert.assertEquals(shares[i], scheds.get(i).getFairShare().getMemory()); } } + + /** + * Check that a given list of steady shares have been assigned to this.scheds. + */ + private void verifyMemorySteadyShares(int... shares) { + Assert.assertEquals(scheds.size(), shares.length); + for (int i = 0; i < shares.length; i++) { + Assert.assertEquals(shares[i], + scheds.get(i).getSteadyFairShare().getMemory()); + } + } /** * Check that a given list of shares have been assigned to this.scheds. @@ -209,4 +247,15 @@ private void verifyCPUShares(int... shares) { Assert.assertEquals(shares[i], scheds.get(i).getFairShare().getVirtualCores()); } } + + /** + * Check that a given list of steady shares have been assigned to this.scheds. + */ + private void verifyCPUSteadyShares(int... shares) { + Assert.assertEquals(scheds.size(), shares.length); + for (int i = 0; i < shares.length; i++) { + Assert.assertEquals(shares[i], + scheds.get(i).getSteadyFairShare().getVirtualCores()); + } + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java index 0ada021..f4a277d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java @@ -58,7 +58,6 @@ import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; -import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.api.records.Priority; @@ -82,13 +81,11 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptImpl; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState; import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer; -import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEventType; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerApplicationAttempt; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerNode; -import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerUtils; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.TestSchedulerUtils; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.AppAddedSchedulerEvent; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.AppAttemptAddedSchedulerEvent; @@ -295,14 +292,19 @@ public void testSimpleFairShareCalculation() throws IOException { createSchedulingRequest(10 * 1024, "root.default", "user1"); scheduler.update(); + scheduler.getQueueManager().getRootQueue() + .setSteadyFairShare(scheduler.getClusterResource()); + scheduler.getQueueManager().getRootQueue().recomputeSteadyShares(); Collection queues = scheduler.getQueueManager().getLeafQueues(); assertEquals(3, queues.size()); - // Divided three ways - betwen the two queues and the default queue + // Divided three ways - between the two queues and the default queue for (FSLeafQueue p : queues) { assertEquals(3414, p.getFairShare().getMemory()); assertEquals(3414, p.getMetrics().getFairShareMB()); + assertEquals(3414, p.getSteadyFairShare().getMemory()); + assertEquals(3414, p.getMetrics().getSteadyFairShareMB()); } } @@ -326,6 +328,9 @@ public void testSimpleHierarchicalFairShareCalculation() throws IOException { createSchedulingRequest(10 * 1024, "root.default", "user1"); scheduler.update(); + scheduler.getQueueManager().getRootQueue() + .setSteadyFairShare(scheduler.getClusterResource()); + scheduler.getQueueManager().getRootQueue().recomputeSteadyShares(); QueueManager queueManager = scheduler.getQueueManager(); Collection queues = queueManager.getLeafQueues(); @@ -336,10 +341,16 @@ public void testSimpleHierarchicalFairShareCalculation() throws IOException { FSLeafQueue queue3 = queueManager.getLeafQueue("parent.queue3", true); assertEquals(capacity / 2, queue1.getFairShare().getMemory()); assertEquals(capacity / 2, queue1.getMetrics().getFairShareMB()); + assertEquals(capacity / 2, queue1.getSteadyFairShare().getMemory()); + assertEquals(capacity / 2, queue1.getMetrics().getSteadyFairShareMB()); assertEquals(capacity / 4, queue2.getFairShare().getMemory()); assertEquals(capacity / 4, queue2.getMetrics().getFairShareMB()); + assertEquals(capacity / 4, queue2.getSteadyFairShare().getMemory()); + assertEquals(capacity / 4, queue2.getMetrics().getSteadyFairShareMB()); assertEquals(capacity / 4, queue3.getFairShare().getMemory()); assertEquals(capacity / 4, queue3.getMetrics().getFairShareMB()); + assertEquals(capacity / 4, queue3.getSteadyFairShare().getMemory()); + assertEquals(capacity / 4, queue3.getMetrics().getSteadyFairShareMB()); } @Test @@ -774,6 +785,9 @@ public void testFairShareAndWeightsInNestedUserQueueRule() throws Exception { createSchedulingRequest(10 * 1024, "root.default", "user3"); scheduler.update(); + scheduler.getQueueManager().getRootQueue() + .setSteadyFairShare(scheduler.getClusterResource()); + scheduler.getQueueManager().getRootQueue().recomputeSteadyShares(); Collection leafQueues = scheduler.getQueueManager() .getLeafQueues(); @@ -783,12 +797,128 @@ public void testFairShareAndWeightsInNestedUserQueueRule() throws Exception { || leaf.getName().equals("root.parentq.user2")) { // assert that the fair share is 1/4th node1's capacity assertEquals(capacity / 4, leaf.getFairShare().getMemory()); + // assert that the steady fair share is 1/4th node1's capacity + assertEquals(capacity / 4, leaf.getSteadyFairShare().getMemory()); // assert weights are equal for both the user queues assertEquals(1.0, leaf.getWeights().getWeight(ResourceType.MEMORY), 0); } } } - + + @Test + public void testSteadyFairShareWithReloadAndNodeAddRemove() throws Exception { + conf.set(FairSchedulerConfiguration.ALLOCATION_FILE, ALLOC_FILE); + + PrintWriter out = new PrintWriter(new FileWriter(ALLOC_FILE)); + out.println(""); + out.println(""); + out.println("fair"); + out.println(""); + out.println(" drf"); + out.println(" "); + out.println(" 1"); + out.println(" "); + out.println(" "); + out.println(" 1"); + out.println(" "); + out.println(""); + out.println(""); + out.close(); + + scheduler.init(conf); + scheduler.start(); + scheduler.reinitialize(conf, resourceManager.getRMContext()); + + // The steady fair share for all queues should be 0 + QueueManager queueManager = scheduler.getQueueManager(); + assertEquals(0, queueManager.getLeafQueue("child1", false) + .getSteadyFairShare().getMemory()); + assertEquals(0, queueManager.getLeafQueue("child2", false) + .getSteadyFairShare().getMemory()); + + // Add one node + RMNode node1 = + MockNodes + .newNodeInfo(1, Resources.createResource(6144), 1, "127.0.0.1"); + NodeAddedSchedulerEvent nodeEvent1 = new NodeAddedSchedulerEvent(node1); + scheduler.handle(nodeEvent1); + assertEquals(6144, scheduler.getClusterResource().getMemory()); + + // The steady fair shares for all queues should be updated + assertEquals(2048, queueManager.getLeafQueue("child1", false) + .getSteadyFairShare().getMemory()); + assertEquals(2048, queueManager.getLeafQueue("child2", false) + .getSteadyFairShare().getMemory()); + + // Reload the allocation configuration file + out = new PrintWriter(new FileWriter(ALLOC_FILE)); + out.println(""); + out.println(""); + out.println("fair"); + out.println(""); + out.println(" drf"); + out.println(" "); + out.println(" 1"); + out.println(" "); + out.println(" "); + out.println(" 2"); + out.println(" "); + out.println(" "); + out.println(" 2"); + out.println(" "); + out.println(""); + out.println(""); + out.close(); + scheduler.reinitialize(conf, resourceManager.getRMContext()); + + // The steady fair shares for all queues should be updated + assertEquals(1024, queueManager.getLeafQueue("child1", false) + .getSteadyFairShare().getMemory()); + assertEquals(2048, queueManager.getLeafQueue("child2", false) + .getSteadyFairShare().getMemory()); + assertEquals(2048, queueManager.getLeafQueue("child3", false) + .getSteadyFairShare().getMemory()); + + // Remove the node, steady fair shares should back to 0 + NodeRemovedSchedulerEvent nodeEvent2 = new NodeRemovedSchedulerEvent(node1); + scheduler.handle(nodeEvent2); + assertEquals(0, scheduler.getClusterResource().getMemory()); + assertEquals(0, queueManager.getLeafQueue("child1", false) + .getSteadyFairShare().getMemory()); + assertEquals(0, queueManager.getLeafQueue("child2", false) + .getSteadyFairShare().getMemory()); + } + + @Test + public void testSteadyFairShareWithQueueCreatedRuntime() throws Exception { + conf.setClass(CommonConfigurationKeys.HADOOP_SECURITY_GROUP_MAPPING, + SimpleGroupsMapping.class, GroupMappingServiceProvider.class); + conf.set(FairSchedulerConfiguration.USER_AS_DEFAULT_QUEUE, "true"); + scheduler.init(conf); + scheduler.start(); + scheduler.reinitialize(conf, resourceManager.getRMContext()); + + // Add one node + RMNode node1 = + MockNodes + .newNodeInfo(1, Resources.createResource(6144), 1, "127.0.0.1"); + NodeAddedSchedulerEvent nodeEvent1 = new NodeAddedSchedulerEvent(node1); + scheduler.handle(nodeEvent1); + assertEquals(6144, scheduler.getClusterResource().getMemory()); + assertEquals(6144, scheduler.getQueueManager().getRootQueue() + .getSteadyFairShare().getMemory()); + assertEquals(6144, scheduler.getQueueManager() + .getLeafQueue("default", false).getSteadyFairShare().getMemory()); + + // Submit one application + ApplicationAttemptId appAttemptId1 = createAppAttemptId(1, 1); + createApplicationWithAMResource(appAttemptId1, "default", "user1", null); + assertEquals(3072, scheduler.getQueueManager() + .getLeafQueue("default", false).getSteadyFairShare().getMemory()); + assertEquals(3072, scheduler.getQueueManager() + .getLeafQueue("user1", false).getSteadyFairShare().getMemory()); + } + /** * Make allocation requests and ensure they are reflected in queue demand. */ @@ -876,7 +1006,7 @@ public void testAppAdditionAndRemoval() throws Exception { } @Test - public void testHierarchicalQueueAllocationFileParsing() throws IOException, SAXException, + public void testHierarchicalQueueAllocationFileParsing() throws IOException, SAXException, AllocationConfigurationException, ParserConfigurationException { conf.set(FairSchedulerConfiguration.ALLOCATION_FILE, ALLOC_FILE); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairSchedulerFairShare.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairSchedulerFairShare.java index 8b8ce93..ab8fcbc 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairSchedulerFairShare.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairSchedulerFairShare.java @@ -109,13 +109,15 @@ public void testFairShareNoAppsRunning() throws IOException { for (FSLeafQueue leaf : leafQueues) { if (leaf.getName().startsWith("root.parentA")) { - assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity - * 100, 0); + assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity, + 0); } else if (leaf.getName().startsWith("root.parentB")) { - assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity - * 100, 0.1); + assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity, + 0); } } + + verifySteadyFairShareMemory(leafQueues, nodeCapacity); } @Test @@ -135,14 +137,15 @@ public void testFairShareOneAppRunning() throws IOException { 100, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA1", false).getFairShare() - .getMemory() - / nodeCapacity * 100, 0.1); + .getMemory() / nodeCapacity * 100, 0.1); assertEquals( 0, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA2", false).getFairShare() - .getMemory() - / nodeCapacity * 100, 0.1); + .getMemory() / nodeCapacity, 0.1); + + verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), + nodeCapacity); } @Test @@ -167,6 +170,9 @@ public void testFairShareMultipleActiveQueuesUnderSameParent() .getMemory() / nodeCapacity * 100, .9); } + + verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), + nodeCapacity); } @Test @@ -206,6 +212,9 @@ public void testFairShareMultipleActiveQueuesUnderDifferentParent() .getLeafQueue("root.parentB.childB1", false).getFairShare() .getMemory() / nodeCapacity * 100, .9); + + verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), + nodeCapacity); } @Test @@ -253,6 +262,9 @@ public void testFairShareResetsToZeroWhenAppsComplete() throws IOException { .getLeafQueue("root.parentA.childA2", false).getFairShare() .getMemory() / nodeCapacity * 100, 0.1); + + verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), + nodeCapacity); } @Test @@ -304,5 +316,45 @@ public void testFairShareWithDRFMultipleActiveQueuesUnderDifferentParent() .getLeafQueue("root.parentB.childB1", false).getFairShare() .getVirtualCores() / nodeVCores * 100, .9); + Collection leafQueues = scheduler.getQueueManager() + .getLeafQueues(); + + for (FSLeafQueue leaf : leafQueues) { + if (leaf.getName().startsWith("root.parentA")) { + assertEquals(0.2, + (double) leaf.getSteadyFairShare().getMemory() / nodeMem, 0.001); + assertEquals(0.2, + (double) leaf.getSteadyFairShare().getVirtualCores() / nodeVCores, + 0.001); + } else if (leaf.getName().startsWith("root.parentB")) { + assertEquals(0.05, + (double) leaf.getSteadyFairShare().getMemory() / nodeMem, 0.001); + assertEquals(0.1, + (double) leaf.getSteadyFairShare().getVirtualCores() / nodeVCores, + 0.001); + } + } + } + + /** + * Verify whether steady fair shares for all leaf queues still follow + * their weight, not related to active/inactive status. + * + * @param leafQueues + * @param nodeCapacity + */ + private void verifySteadyFairShareMemory(Collection leafQueues, + int nodeCapacity) { + for (FSLeafQueue leaf : leafQueues) { + if (leaf.getName().startsWith("root.parentA")) { + assertEquals(0.2, + (double) leaf.getSteadyFairShare().getMemory() / nodeCapacity, + 0.001); + } else if (leaf.getName().startsWith("root.parentB")) { + assertEquals(0.05, + (double) leaf.getSteadyFairShare().getMemory() / nodeCapacity, + 0.001); + } + } } }