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/AbstractResourceUsage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AbstractResourceUsage.java index c2953236f47..3203543f82c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AbstractResourceUsage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AbstractResourceUsage.java @@ -21,6 +21,7 @@ package org.apache.hadoop.yarn.server.resourcemanager.scheduler; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -38,17 +39,20 @@ import org.apache.hadoop.yarn.util.resource.Resources; public class AbstractResourceUsage { protected ReadLock readLock; protected WriteLock writeLock; - protected Map usages; + protected final Map usages; + private final UsageByLabel noLabelUsages; // short for no-label :) - private static final String NL = CommonNodeLabelsManager.NO_LABEL; public AbstractResourceUsage() { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); readLock = lock.readLock(); writeLock = lock.writeLock(); - usages = new HashMap(); - usages.put(NL, new UsageByLabel(NL)); + usages = new HashMap<>(); + + // For default label, avoid map for faster access. + noLabelUsages = new UsageByLabel(); + usages.put(CommonNodeLabelsManager.NO_LABEL, noLabelUsages); } // Usage enum here to make implement cleaner @@ -57,41 +61,40 @@ public class AbstractResourceUsage { // be written by ordering policies USED(0), PENDING(1), AMUSED(2), RESERVED(3), CACHED_USED(4), CACHED_PENDING( 5), AMLIMIT(6), MIN_RESOURCE(7), MAX_RESOURCE(8), EFF_MIN_RESOURCE( - 9), EFF_MAX_RESOURCE( - 10), EFF_MIN_RESOURCE_UP(11), EFF_MAX_RESOURCE_UP(12); + 9), EFF_MAX_RESOURCE(10); private int idx; - private ResourceType(int value) { + ResourceType(int value) { this.idx = value; } } public static class UsageByLabel { // usage by label, contains all UsageType - private Resource[] resArr; + private final AtomicReferenceArray resArr; - public UsageByLabel(String label) { - resArr = new Resource[ResourceType.values().length]; - for (int i = 0; i < resArr.length; i++) { - resArr[i] = Resource.newInstance(0, 0); - }; + public UsageByLabel() { + resArr = new AtomicReferenceArray<>(ResourceType.values().length); + for (int i = 0; i < resArr.length(); i++) { + resArr.set(i, Resource.newInstance(0, 0)); + } } public Resource getUsed() { - return resArr[ResourceType.USED.idx]; + return resArr.get(ResourceType.USED.idx); } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("{used=" + resArr[0] + "%, "); - sb.append("pending=" + resArr[1] + "%, "); - sb.append("am_used=" + resArr[2] + "%, "); - sb.append("reserved=" + resArr[3] + "%}"); - sb.append("min_eff=" + resArr[9] + "%, "); - sb.append("max_eff=" + resArr[10] + "%}"); - sb.append("min_effup=" + resArr[11] + "%, "); + sb.append("{used=" + resArr.get(ResourceType.USED.idx) + ", "); + sb.append("pending=" + resArr.get(ResourceType.PENDING.idx) + ", "); + sb.append("am_used=" + resArr.get(ResourceType.AMUSED.idx) + ", "); + sb.append("reserved=" + resArr.get(ResourceType.RESERVED.idx) + ", "); + sb.append("min_eff=" + resArr.get(ResourceType.EFF_MIN_RESOURCE.idx) + ", "); + sb.append( + "max_eff=" + resArr.get(ResourceType.EFF_MAX_RESOURCE.idx) + "}"); return sb.toString(); } } @@ -104,8 +107,8 @@ public class AbstractResourceUsage { } protected Resource _get(String label, ResourceType type) { - if (label == null) { - label = RMNodeLabelsManager.NO_LABEL; + if (label == null || label.equals(RMNodeLabelsManager.NO_LABEL)) { + return normalize(noLabelUsages.resArr.get(type.idx)); } try { @@ -114,7 +117,7 @@ public class AbstractResourceUsage { if (null == usage) { return Resources.none(); } - return normalize(usage.resArr[type.idx]); + return normalize(usage.resArr.get(type.idx)); } finally { readLock.unlock(); } @@ -126,7 +129,7 @@ public class AbstractResourceUsage { Resource allOfType = Resources.createResource(0); for (Map.Entry usageEntry : usages.entrySet()) { //all usages types are initialized - Resources.addTo(allOfType, usageEntry.getValue().resArr[type.idx]); + Resources.addTo(allOfType, usageEntry.getValue().resArr.get(type.idx)); } return allOfType; } finally { @@ -135,11 +138,12 @@ public class AbstractResourceUsage { } private UsageByLabel getAndAddIfMissing(String label) { - if (label == null) { - label = RMNodeLabelsManager.NO_LABEL; + if (label == null || label.equals(RMNodeLabelsManager.NO_LABEL)) { + return noLabelUsages; } + if (!usages.containsKey(label)) { - UsageByLabel u = new UsageByLabel(label); + UsageByLabel u = new UsageByLabel(); usages.put(label, u); return u; } @@ -151,7 +155,7 @@ public class AbstractResourceUsage { try { writeLock.lock(); UsageByLabel usage = getAndAddIfMissing(label); - usage.resArr[type.idx] = res; + usage.resArr.set(type.idx, res); } finally { writeLock.unlock(); } @@ -161,7 +165,8 @@ public class AbstractResourceUsage { try { writeLock.lock(); UsageByLabel usage = getAndAddIfMissing(label); - Resources.addTo(usage.resArr[type.idx], res); + usage.resArr.set(type.idx, + Resources.add(usage.resArr.get(type.idx), res)); } finally { writeLock.unlock(); } @@ -171,7 +176,8 @@ public class AbstractResourceUsage { try { writeLock.lock(); UsageByLabel usage = getAndAddIfMissing(label); - Resources.subtractFrom(usage.resArr[type.idx], res); + usage.resArr.set(type.idx, + Resources.subtract(usage.resArr.get(type.idx), res)); } finally { writeLock.unlock(); } 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/AbstractCSQueue.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/AbstractCSQueue.java index 9caf5891000..140ea5dc903 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/AbstractCSQueue.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/AbstractCSQueue.java @@ -932,7 +932,7 @@ public abstract class AbstractCSQueue implements CSQueue { queueUsage.incUsed(nodeLabel, resourceToInc); CSQueueUtils.updateUsedCapacity(resourceCalculator, labelManager.getResourceByLabel(nodeLabel, Resources.none()), - Resources.none(), nodeLabel, this); + nodeLabel, this); if (null != parent) { parent.incUsedResource(nodeLabel, resourceToInc, null); } @@ -948,7 +948,7 @@ public abstract class AbstractCSQueue implements CSQueue { queueUsage.decUsed(nodeLabel, resourceToDec); CSQueueUtils.updateUsedCapacity(resourceCalculator, labelManager.getResourceByLabel(nodeLabel, Resources.none()), - Resources.none(), nodeLabel, this); + nodeLabel, this); if (null != parent) { parent.decUsedResource(nodeLabel, resourceToDec, null); } 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/CSQueueUtils.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/CSQueueUtils.java index 81dec80d0eb..6daca5158a3 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/CSQueueUtils.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/CSQueueUtils.java @@ -180,8 +180,8 @@ class CSQueueUtils { * used resource for all partitions of this queue. */ public static void updateUsedCapacity(final ResourceCalculator rc, - final Resource totalPartitionResource, Resource clusterResource, - String nodePartition, AbstractCSQueue childQueue) { + final Resource totalPartitionResource, String nodePartition, + AbstractCSQueue childQueue) { QueueCapacities queueCapacities = childQueue.getQueueCapacities(); CSQueueMetrics queueMetrics = childQueue.getMetrics(); ResourceUsage queueResourceUsage = childQueue.getQueueResourceUsage(); @@ -287,11 +287,11 @@ class CSQueueUtils { for (String partition : Sets.union(queueCapacities.getNodePartitionsSet(), queueResourceUsage.getNodePartitionsSet())) { updateUsedCapacity(rc, nlm.getResourceByLabel(partition, cluster), - cluster, partition, childQueue); + partition, childQueue); } } else { updateUsedCapacity(rc, nlm.getResourceByLabel(nodePartition, cluster), - cluster, nodePartition, childQueue); + nodePartition, childQueue); } // Update queue metrics w.r.t node labels. In a generic way, we can 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/ParentQueue.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/ParentQueue.java index a427fb135ab..c198d135ed2 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/ParentQueue.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/ParentQueue.java @@ -739,8 +739,8 @@ public class ParentQueue extends AbstractCSQueue { child.getQueueResourceUsage().getUsed(nodePartition)); // Get child's max resource - Resource childConfiguredMaxResource = getEffectiveMaxCapacityDown( - nodePartition, minimumAllocation); + Resource childConfiguredMaxResource = child + .getEffectiveMaxCapacityDown(nodePartition, minimumAllocation); // Child's limit should be capped by child configured max resource childLimit = 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/TestCapacityScheduler.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/TestCapacityScheduler.java index 23a371abffb..e91f7341a0a 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/TestCapacityScheduler.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/TestCapacityScheduler.java @@ -4307,7 +4307,7 @@ public class TestCapacityScheduler { null, null, NULL_UPDATE_REQUESTS); CapacityScheduler.schedule(cs); } - assertEquals("P2 Used Resource should be 7 GB", 7 * GB, + assertEquals("P2 Used Resource should be 8 GB", 8 * GB, cs.getQueue("p2").getUsedResources().getMemorySize()); //Free a container from X1