diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java index 2a6657aa5df..5702488e6c6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java @@ -589,8 +589,17 @@ private void untrackContainerForPreemption(RMContainer container) { } } + public void logPreemptContainerPreCheckInfo(String failedInfo) { + if (LOG.isDebugEnabled()){ + LOG.debug("FairScheduler Preemption Record: " + "[Preemption step 1]." + + " Container preemption pre check failed." + + " Because: " + failedInfo); + } + } + boolean canContainerBePreempted(RMContainer container, - Resource alreadyConsideringForPreemption) { + Resource alreadyConsideringForPreemption, + FSAppAttempt starvedApp) { if (!isPreemptable()) { return false; } @@ -610,6 +619,13 @@ boolean canContainerBePreempted(RMContainer container, } } + // We should not preempt self! + if (getApplicationId().equals(starvedApp.getApplicationId())) { + logPreemptContainerPreCheckInfo( + "this container belongs to self!"); + return false; + } + // Check if the app's allocation will be over its fairshare even // after preempting this container Resource usageAfterPreemption = getUsageAfterPreemptingContainer( diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSPreemptionThread.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSPreemptionThread.java index 4c830523cb4..13c5906e592 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSPreemptionThread.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSPreemptionThread.java @@ -28,7 +28,10 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerUtils; import org.apache.hadoop.yarn.util.resource.Resources; +import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -90,6 +93,16 @@ public void run() { } } + private static class CreationTimeComparator implements + Comparator, Serializable { + + private static final long serialVersionUID = 1; + + public int compare(RMContainer c1, RMContainer c2) { + return (int)(c2.getCreationTime() - c1.getCreationTime()); + } + } + /** * Given an app, identify containers to preempt to satisfy the app's * starvation. @@ -113,9 +126,11 @@ public void run() { .getNodesByResourceName(rr.getResourceName()); for (int i = 0; i < rr.getNumContainers(); i++) { PreemptableContainers bestContainers = - getBestPreemptableContainers(rr, potentialNodes); + getBestPreemptableContainers(rr, potentialNodes, starvedApp); if (bestContainers != null) { List containers = bestContainers.getAllContainers(); + // Preempt short-running containers firstly + Collections.sort(containers, new CreationTimeComparator()); if (containers.size() > 0) { containersToPreempt.addAll(containers); // Reserve the containers for the starved app @@ -136,14 +151,15 @@ public void run() { } private PreemptableContainers identifyContainersToPreemptForOneContainer( - List potentialNodes, ResourceRequest rr) { + List potentialNodes, ResourceRequest rr, + FSAppAttempt starvedApp) { PreemptableContainers bestContainers = null; int maxAMContainers = Integer.MAX_VALUE; for (FSSchedulerNode node : potentialNodes) { PreemptableContainers preemptableContainers = identifyContainersToPreemptOnNode( - rr.getCapability(), node, maxAMContainers); + rr.getCapability(), node, maxAMContainers, starvedApp); if (preemptableContainers != null) { // This set is better than any previously identified set. @@ -171,7 +187,8 @@ private PreemptableContainers identifyContainersToPreemptForOneContainer( * maxAMContainers if such a list exists; null otherwise. */ private PreemptableContainers identifyContainersToPreemptOnNode( - Resource request, FSSchedulerNode node, int maxAMContainers) { + Resource request, FSSchedulerNode node, int maxAMContainers, + FSAppAttempt starvedApp) { PreemptableContainers preemptableContainers = new PreemptableContainers(maxAMContainers); @@ -191,7 +208,8 @@ private PreemptableContainers identifyContainersToPreemptOnNode( ApplicationId appId = app.getApplicationId(); if (app.canContainerBePreempted(container, - preemptableContainers.getResourcesToPreemptForApp(appId))) { + preemptableContainers.getResourcesToPreemptForApp(appId), + starvedApp)) { // Flag container for preemption if (!preemptableContainers.addContainer(container, appId)) { return null; @@ -237,9 +255,10 @@ private void preemptContainers(List containers) { * @return the list of best preemptable containers for the resource request */ private PreemptableContainers getBestPreemptableContainers(ResourceRequest rr, - List potentialNodes) { + List potentialNodes, FSAppAttempt starvedApp) { PreemptableContainers bestContainers = - identifyContainersToPreemptForOneContainer(potentialNodes, rr); + identifyContainersToPreemptForOneContainer( + potentialNodes, rr, starvedApp); if (rr.getRelaxLocality() && !ResourceRequest.isAnyLocation(rr.getResourceName()) @@ -249,7 +268,8 @@ private PreemptableContainers getBestPreemptableContainers(ResourceRequest rr, scheduler.getNodeTracker().getAllNodes(); remainingNodes.removeAll(potentialNodes); PreemptableContainers spareContainers = - identifyContainersToPreemptForOneContainer(remainingNodes, rr); + identifyContainersToPreemptForOneContainer( + remainingNodes, rr, starvedApp); if (spareContainers != null && spareContainers.numAMContainers < bestContainers.numAMContainers) { bestContainers = spareContainers;