YARN-7469. Capacity Scheduler Intra-queue preemption: User can starve if newest app is exactly at user limit. Contributed by Eric Payne.

(cherry picked from commit 61ace174cd)
(cherry picked from commit c3fb49667a)
This commit is contained in:
Sunil G 2017-11-16 22:34:23 +05:30 committed by Andrew Wang
parent b1712f9c1f
commit 0510ceede6
3 changed files with 44 additions and 0 deletions

View File

@ -203,6 +203,12 @@ public class FifoIntraQueuePreemptionPlugin
Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.selected); Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.selected);
Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.getAMUsed()); Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.getAMUsed());
if (context.getIntraQueuePreemptionOrderPolicy()
.equals(IntraQueuePreemptionOrderPolicy.USERLIMIT_FIRST)) {
Resources.subtractFromNonNegative(preemtableFromApp,
tmpApp.getFiCaSchedulerApp().getCSLeafQueue().getMinimumAllocation());
}
// Calculate toBePreempted from apps as follows: // Calculate toBePreempted from apps as follows:
// app.preemptable = min(max(app.used - app.selected - app.ideal, 0), // app.preemptable = min(max(app.used - app.selected - app.ideal, 0),
// intra_q_preemptable) // intra_q_preemptable)

View File

@ -358,6 +358,9 @@ public class ProportionalCapacityPreemptionPolicyMockFramework {
queue = (LeafQueue) nameToCSQueues.get(queueName); queue = (LeafQueue) nameToCSQueues.get(queueName);
queue.getApplications().add(app); queue.getApplications().add(app);
queue.getAllApplications().add(app); queue.getAllApplications().add(app);
when(queue.getMinimumAllocation())
.thenReturn(Resource.newInstance(1,1));
when(app.getCSLeafQueue()).thenReturn(queue);
HashSet<String> users = userMap.get(queueName); HashSet<String> users = userMap.get(queueName);
if (null == users) { if (null == users) {

View File

@ -896,4 +896,39 @@ public class TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor( new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1)))); getAppAttemptId(1))));
} }
@Test
public void testSimpleIntraQueuePreemptionOneUserUnderOneUserAtOneUserAbove()
throws IOException {
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 1 0]);" + // root
"-a(=[100 100 100 1 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,65,false,0,user1);" +
"a\t" // app2 in a
+ "(1,1,n1,,35,false,0,user2);" +
"a\t" // app3 in a
+ "(1,1,n1,,0,false,1,user3)"
;
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 is right at its user limit and app1 needs one resource. Should
// preempt 1 container.
verify(mDisp, times(1)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
} }