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/capacity/UsersManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java index cf9dead1837..2b9d09d4b81 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java @@ -773,13 +773,15 @@ Resource computeUserLimit(String userName, Resource clusterResource, * User limit resource is determined by: max(currentCapacity / #activeUsers, * currentCapacity * user-limit-percentage%) */ + + float effectiveUserLimit = Math.max(getUserLimit() / 100.0f, + 1.0f / Math.max(getNumActiveUsers(), 1)); Resource userLimitResource = Resources.max(resourceCalculator, partitionResource, Resources.divideAndCeil(resourceCalculator, resourceUsed, usersSummedByWeight), - Resources.divideAndCeil(resourceCalculator, - Resources.multiplyAndRoundDown(currentCapacity, getUserLimit()), - 100)); + Resources.multiplyAndRoundDown(currentCapacity, + effectiveUserLimit)); // User limit is capped by maxUserLimit // - maxUserLimit = queueCapacity * user-limit-factor diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestUsersManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestUsersManager.java index 5b79ee2e255..a825ece5926 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestUsersManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestUsersManager.java @@ -23,6 +23,8 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.junit.Assert.assertEquals; +import org.apache.hadoop.util.Time; +import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -48,6 +50,7 @@ private static final String TEST_USER = "test"; private UsersManager usersManager; + private final DefaultResourceCalculator resourceCalculator = new DefaultResourceCalculator(); @Mock private AutoCreatedLeafQueue lQueue; @@ -67,7 +70,7 @@ public void setup() { lQueue, labelMgr, context, - new DefaultResourceCalculator()); + resourceCalculator); when(lQueue.getMinimumAllocation()).thenReturn(MINIMUM_ALLOCATION); when(lQueue.getEffectiveMaxCapacityDown(anyString(), any(Resource.class))) @@ -81,6 +84,38 @@ public void setup() { CapacitySchedulerConfiguration.DEFAULT_USER_LIMIT_FACTOR); } + @Test + public void testComputeUserLimitWithMinimumUserLimitPercent() { + when(lQueue.getEffectiveCapacity(anyString())) + .thenReturn(NON_ZERO_CAPACITY); + + UsersManager.User user1 = usersManager.getUserAndAddIfAbsent("test1"); + UsersManager.User user2 = usersManager.getUserAndAddIfAbsent("test2"); + user1.setAndUpdateUsageRatio(resourceCalculator, + Resources.createResource(1024, 1), ""); + user2.setAndUpdateUsageRatio(resourceCalculator, + Resources.createResource(1024, 1), ""); + user1.userResourceUsage.incUsed(Resources.createResource(1024, 1)); + user2.userResourceUsage.incUsed(Resources.createResource(1024, 1)); + user1.activateApplication(); + user2.activateApplication(); + usersManager.updateUserWeights(); + usersManager.activateApplication("test1", + ApplicationId.newInstance(Time.monotonicNow(), 1)); + usersManager.activateApplication("test2", + ApplicationId.newInstance(Time.monotonicNow(), 2)); + usersManager.setUsageRatio("", 0.3f); + + // check without minimum-user-limit-percent + checkLimit(NON_ZERO_CAPACITY); + + usersManager.setUserLimit(10); + // Sum of active user weight is 2. According to MULP definition the current + // user limit percent is 50 (2 users present), and can not go under 10. + checkLimit(Resources.divideAndCeil(resourceCalculator, NON_ZERO_CAPACITY, + 2)); + } + @Test public void testComputeUserLimitWithZeroCapacityQueue() { when(lQueue.getEffectiveCapacity(anyString()))