|
69 | 69 | import org.apache.hadoop.yarn.server.resourcemanager.scheduler.common.fica.FiCaSchedulerNode; |
70 | 70 | import org.apache.hadoop.yarn.server.resourcemanager.security.RMContainerTokenSecretManager; |
71 | 71 | import org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator; |
| 72 | +import org.apache.hadoop.yarn.util.resource.DominantResourceCalculator; |
72 | 73 | import org.apache.hadoop.yarn.util.resource.ResourceCalculator; |
73 | 74 | import org.apache.hadoop.yarn.util.resource.Resources; |
74 | 75 | import static org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration.PREFIX; |
@@ -878,6 +879,69 @@ public RMNodeLabelsManager createNodeLabelManager() { |
878 | 879 | rm.stop(); |
879 | 880 | } |
880 | 881 |
|
| 882 | + // Test that max AM limit is correct in the case where one resource is |
| 883 | + // depleted but the other is not. Use DominantResourceCalculator. |
| 884 | + @Test |
| 885 | + public void testAMResourceLimitWithDRCAndFullParent() throws Exception { |
| 886 | + CapacitySchedulerConfiguration csConf = |
| 887 | + new CapacitySchedulerConfiguration(); |
| 888 | + setupQueueConfiguration(csConf); |
| 889 | + csConf.setFloat(CapacitySchedulerConfiguration. |
| 890 | + MAXIMUM_APPLICATION_MASTERS_RESOURCE_PERCENT, 0.3f); |
| 891 | + |
| 892 | + // Total cluster resources. |
| 893 | + Resource clusterResource = Resources.createResource(100 * GB, 1000); |
| 894 | + |
| 895 | + CapacitySchedulerQueueContext queueContext = new CapacitySchedulerQueueContext( |
| 896 | + createCSContext(csConf, new DominantResourceCalculator(), Resources.createResource(GB), |
| 897 | + Resources.createResource(16*GB), clusterResource)); |
| 898 | + |
| 899 | + // Set up queue hierarchy. |
| 900 | + CSQueueStore queues = new CSQueueStore(); |
| 901 | + CSQueue rootQueue = CapacitySchedulerQueueManager.parseQueue(queueContext, |
| 902 | + csConf, null, "root", queues, queues, TestUtils.spyHook); |
| 903 | + rootQueue.updateClusterResource(clusterResource, |
| 904 | + new ResourceLimits(clusterResource)); |
| 905 | + |
| 906 | + // Queue "queueA" has a 30% capacity guarantee. The max pct of "queueA" that |
| 907 | + // can be used for AMs is 30%. So, 30% of <memory: 100GB, vCores: 1000> is |
| 908 | + // <memory: 30GB, vCores: 30>, which is the guaranteed capacity of "queueA". |
| 909 | + // 30% of that (rounded to the nearest 1GB) is <memory: 9GB, vCores: 9>. The |
| 910 | + // max AM queue limit should never be less than that for any resource. |
| 911 | + LeafQueue queueA = TestLeafQueue.stubLeafQueue((LeafQueue)queues.get(A)); |
| 912 | + queueA.setCapacity(30.0f); |
| 913 | + queueA.setUserLimitFactor(10f); |
| 914 | + queueA.setMaxAMResourcePerQueuePercent(0.3f); |
| 915 | + // Make sure "queueA" knows the total cluster resource. |
| 916 | + queueA.updateClusterResource(clusterResource, new ResourceLimits( |
| 917 | + clusterResource)); |
| 918 | + // Get "queueA"'s guaranteed capacity (<memory: 30GB, vCores: 300>). |
| 919 | + Resource capacity = |
| 920 | + Resources.multiply(clusterResource, (queueA.getCapacity()/100)); |
| 921 | + // Limit is the actual resources available to "queueA". The following |
| 922 | + // simulates the case where a second queue ("queueB") has "borrowed" almost |
| 923 | + // all of "queueA"'s resources because "queueB" has a max capacity of 100% |
| 924 | + // and has gone well over its guaranteed capacity. In this case, "queueB" |
| 925 | + // has used 99GB of memory and used 505 vCores. This is to make vCores |
| 926 | + // dominant in the calculations for the available resources. |
| 927 | + when(queueA.getEffectiveCapacity(any())).thenReturn(capacity); |
| 928 | + Resource limit = Resource.newInstance(1024, 495); |
| 929 | + ResourceLimits currentResourceLimits = |
| 930 | + new ResourceLimits(limit, Resources.none()); |
| 931 | + queueA.updateClusterResource(clusterResource, currentResourceLimits); |
| 932 | + Resource expectedAmLimit = Resources.multiply(capacity, |
| 933 | + queueA.getMaxAMResourcePerQueuePercent()); |
| 934 | + Resource amLimit = queueA.calculateAndGetAMResourceLimit(); |
| 935 | + assertTrue("AM memory limit is less than expected: Expected: " + |
| 936 | + expectedAmLimit.getMemorySize() + "; Computed: " |
| 937 | + + amLimit.getMemorySize(), |
| 938 | + amLimit.getMemorySize() >= expectedAmLimit.getMemorySize()); |
| 939 | + assertTrue("AM vCore limit is less than expected: Expected: " + |
| 940 | + expectedAmLimit.getVirtualCores() + "; Computed: " |
| 941 | + + amLimit.getVirtualCores(), |
| 942 | + amLimit.getVirtualCores() >= expectedAmLimit.getVirtualCores()); |
| 943 | + } |
| 944 | + |
881 | 945 | private CapacitySchedulerContext createCSContext(CapacitySchedulerConfiguration csConf, |
882 | 946 | ResourceCalculator rc, Resource minResource, Resource maxResource, Resource clusterResource) { |
883 | 947 | YarnConfiguration conf = new YarnConfiguration(); |
|
0 commit comments