@Override void updateInternal() { readLock.lock(); try { policy.computeShares(runnableApps, getFairShare()); } finally { readLock.unlock(); } }
/** * Is a queue being starved for its fair share threshold. */ @VisibleForTesting boolean isStarvedForFairShare() { return isStarved( Resources.multiply(getFairShare(), getFairSharePreemptionThreshold())); }
@Override public void recomputeShares() { readLock.lock(); try { policy.computeShares(runnableApps, getFairShare()); } finally { readLock.unlock(); } }
/** * Is a queue being starved for its fair share threshold. */ @VisibleForTesting boolean isStarvedForFairShare() { return isStarved( Resources.multiply(getFairShare(), getFairSharePreemptionThreshold())); }
@Override public void recomputeShares() { readLock.lock(); try { policy.computeShares(runnableApps, getFairShare()); } finally { readLock.unlock(); } }
/** * Helper method to check if the queue should preempt containers * * @return true if check passes (can preempt) or false otherwise */ private boolean preemptContainerPreCheck() { return parent.getPolicy().checkIfUsageOverFairShare(getResourceUsage(), getFairShare()); }
/** * Helper method to check if the queue should preempt containers * * @return true if check passes (can preempt) or false otherwise */ private boolean preemptContainerPreCheck() { return parent.getPolicy().checkIfUsageOverFairShare(getResourceUsage(), getFairShare()); }
/** * Check whether this queue can run this application master under the * maxAMShare limit * * @param amResource * @return true if this queue can run */ public boolean canRunAppAM(Resource amResource) { float maxAMShare = scheduler.getAllocationConfiguration().getQueueMaxAMShare(getName()); if (Math.abs(maxAMShare - -1.0f) < 0.0001) { return true; } Resource maxAMResource = Resources.multiply(getFairShare(), maxAMShare); Resource ifRunAMResource = Resources.add(amResourceUsage, amResource); return !policy .checkIfAMResourceUsageOverLimit(ifRunAMResource, maxAMResource); }
/** * Check whether this queue can run this application master under the * maxAMShare limit * * @param amResource * @return true if this queue can run */ public boolean canRunAppAM(Resource amResource) { float maxAMShare = scheduler.getAllocationConfiguration().getQueueMaxAMShare(getName()); if (Math.abs(maxAMShare - -1.0f) < 0.0001) { return true; } Resource maxAMResource = Resources.multiply(getFairShare(), maxAMShare); Resource ifRunAMResource = Resources.add(amResourceUsage, amResource); return !policy .checkIfAMResourceUsageOverLimit(ifRunAMResource, maxAMResource); }
@Override public Resource assignContainer(FSSchedulerNode node) { Resource assigned = none(); if (LOG.isDebugEnabled()) { LOG.debug("Node " + node.getNodeName() + " offered to queue: " + getName() + " fairShare: " + getFairShare()); } if (!assignContainerPreCheck(node)) { return assigned; } for (FSAppAttempt sched : fetchAppsWithDemand(true)) { if (SchedulerAppUtils.isPlaceBlacklisted(sched, node, LOG)) { continue; } assigned = sched.assignContainer(node); if (!assigned.equals(none())) { if (LOG.isDebugEnabled()) { LOG.debug("Assigned container in queue:" + getName() + " " + "container:" + assigned); } break; } } return assigned; }
@Override protected void dumpStateInternal(StringBuilder sb) { sb.append("{Name: " + getName() + ", Weight: " + weights + ", Policy: " + policy.getName() + ", FairShare: " + getFairShare() + ", SteadyFairShare: " + getSteadyFairShare() + ", MaxShare: " + getMaxShare() + ", MinShare: " + minShare + ", ResourceUsage: " + getResourceUsage() + ", Demand: " + getDemand() + ", Runnable: " + getNumRunnableApps() + ", NumPendingApps: " + getNumPendingApps() + ", NonRunnable: " + getNumNonRunnableApps() + ", MaxAMShare: " + maxAMShare + ", MaxAMResource: " + computeMaxAMResource() + ", AMResourceUsage: " + getAmResourceUsage() + ", LastTimeAtMinShare: " + lastTimeAtMinShare + "}"); }
/** * Compute the maximum resource AM can use. The value is the result of * multiplying FairShare and maxAMShare. If FairShare is zero, use * min(maxShare, available resource) instead to prevent zero value for * maximum AM resource since it forbids any job running in the queue. * * @return the maximum resource AM can use */ private Resource computeMaxAMResource() { Resource maxResource = Resources.clone(getFairShare()); if (maxResource.getMemorySize() == 0) { maxResource.setMemorySize( Math.min(scheduler.getRootQueueMetrics().getAvailableMB(), getMaxShare().getMemorySize())); } if (maxResource.getVirtualCores() == 0) { maxResource.setVirtualCores(Math.min( scheduler.getRootQueueMetrics().getAvailableVirtualCores(), getMaxShare().getVirtualCores())); } // Round up to allow AM to run when there is only one vcore on the cluster return Resources.multiplyAndRoundUp(maxResource, maxAMShare); }
@Test public void testFairShareNoAppsRunning() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); scheduler.update(); // No apps are running in the cluster,verify if fair share is zero // for all queues under parentA and parentB. Collection<FSLeafQueue> leafQueues = scheduler.getQueueManager() .getLeafQueues(); for (FSLeafQueue leaf : leafQueues) { if (leaf.getName().startsWith("root.parentA")) { assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity, 0); } else if (leaf.getName().startsWith("root.parentB")) { assertEquals(0, (double) leaf.getFairShare().getMemory() / nodeCapacity, 0); } } verifySteadyFairShareMemory(leafQueues, nodeCapacity); }
@Test public void testFairShareNoAppsRunning() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); scheduler.update(); // No apps are running in the cluster,verify if fair share is zero // for all queues under parentA and parentB. Collection<FSLeafQueue> leafQueues = scheduler.getQueueManager() .getLeafQueues(); for (FSLeafQueue leaf : leafQueues) { if (leaf.getName().startsWith("root.parentA")) { assertEquals(0, (double) leaf.getFairShare().getMemorySize() / nodeCapacity, 0); } else if (leaf.getName().startsWith("root.parentB")) { assertEquals(0, (double) leaf.getFairShare().getMemorySize() / nodeCapacity, 0); } } verifySteadyFairShareMemory(leafQueues, nodeCapacity); }
@Test public void testFairShareOneAppRunning() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); // Run a app in a childA1. Verify whether fair share is 100% in childA1, // since it is the only active queue. // Also verify if fair share is 0 for childA2. since no app is // running in it. createSchedulingRequest(2 * 1024, "root.parentA.childA1", "user1"); scheduler.update(); assertEquals( 100, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA1", false).getFairShare() .getMemory() / nodeCapacity * 100, 0.1); assertEquals( 0, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA2", false).getFairShare() .getMemory() / nodeCapacity, 0.1); verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), nodeCapacity); }
@Test public void testFairShareOneAppRunning() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); // Run a app in a childA1. Verify whether fair share is 100% in childA1, // since it is the only active queue. // Also verify if fair share is 0 for childA2. since no app is // running in it. createSchedulingRequest(2 * 1024, "root.parentA.childA1", "user1"); scheduler.update(); assertEquals( 100, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA1", false).getFairShare() .getMemorySize() / nodeCapacity * 100, 0.1); assertEquals( 0, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA2", false).getFairShare() .getMemorySize() / nodeCapacity, 0.1); verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), nodeCapacity); }
40, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA" + i, false).getFairShare() .getMemorySize() / nodeCapacity * 100, .9); 10, (double) scheduler.getQueueManager() .getLeafQueue("root.parentB.childB1", false).getFairShare() .getMemorySize() / nodeCapacity * 100, .9);
@Test public void testFairShareMultipleActiveQueuesUnderSameParent() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); // Run apps in childA1,childA2,childA3 createSchedulingRequest(2 * 1024, "root.parentA.childA1", "user1"); createSchedulingRequest(2 * 1024, "root.parentA.childA2", "user2"); createSchedulingRequest(2 * 1024, "root.parentA.childA3", "user3"); scheduler.update(); // Verify if fair share is 100 / 3 = 33% for (int i = 1; i <= 3; i++) { assertEquals( 33, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA" + i, false).getFairShare() .getMemory() / nodeCapacity * 100, .9); } verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), nodeCapacity); }
@Test public void testFairShareMultipleActiveQueuesUnderSameParent() throws IOException { int nodeCapacity = 16 * 1024; createClusterWithQueuesAndOneNode(nodeCapacity, "fair"); // Run apps in childA1,childA2,childA3 createSchedulingRequest(2 * 1024, "root.parentA.childA1", "user1"); createSchedulingRequest(2 * 1024, "root.parentA.childA2", "user2"); createSchedulingRequest(2 * 1024, "root.parentA.childA3", "user3"); scheduler.update(); // Verify if fair share is 100 / 3 = 33% for (int i = 1; i <= 3; i++) { assertEquals( 33, (double) scheduler.getQueueManager() .getLeafQueue("root.parentA.childA" + i, false).getFairShare() .getMemorySize() / nodeCapacity * 100, .9); } verifySteadyFairShareMemory(scheduler.getQueueManager().getLeafQueues(), nodeCapacity); }
@Test public void testSimpleFairShareCalculation() throws IOException { scheduler.init(conf); scheduler.start(); scheduler.reinitialize(conf, resourceManager.getRMContext()); // Add one big node (only care about aggregate capacity) RMNode node1 = MockNodes.newNodeInfo(1, Resources.createResource(10 * 1024), 1, "127.0.0.1"); NodeAddedSchedulerEvent nodeEvent1 = new NodeAddedSchedulerEvent(node1); scheduler.handle(nodeEvent1); // Have two queues which want entire cluster capacity createSchedulingRequest(10 * 1024, "queue1", "user1"); createSchedulingRequest(10 * 1024, "queue2", "user1"); createSchedulingRequest(10 * 1024, "root.default", "user1"); scheduler.update(); scheduler.getQueueManager().getRootQueue() .setSteadyFairShare(scheduler.getClusterResource()); scheduler.getQueueManager().getRootQueue().recomputeSteadyShares(); Collection<FSLeafQueue> queues = scheduler.getQueueManager().getLeafQueues(); assertEquals(3, queues.size()); // Divided three ways - between the two queues and the default queue for (FSLeafQueue p : queues) { assertEquals(3414, p.getFairShare().getMemorySize()); assertEquals(3414, p.getMetrics().getFairShareMB()); assertEquals(3414, p.getSteadyFairShare().getMemorySize()); assertEquals(3414, p.getMetrics().getSteadyFairShareMB()); } }