diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ContainerStatus.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ContainerStatus.java index 5ccf6dc..238ff0a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ContainerStatus.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ContainerStatus.java @@ -114,4 +114,16 @@ public static ContainerStatus newInstance(ContainerId containerId, @Private @Unstable public abstract void setDiagnostics(String diagnostics); + + /** + * Get the ResourceUtilization of the container. + * @return ResourceUtilization of the container + */ + @Public + @Unstable + public abstract ResourceUtilization getUtilization(); + + @Private + @Unstable + public abstract void setUtilization(ResourceUtilization utilization); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ResourceUtilization.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ResourceUtilization.java new file mode 100644 index 0000000..f97235c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ResourceUtilization.java @@ -0,0 +1,130 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.api.records; + +import org.apache.hadoop.classification.InterfaceAudience.Public; +import org.apache.hadoop.classification.InterfaceStability.Evolving; +import org.apache.hadoop.classification.InterfaceStability.Stable; +import org.apache.hadoop.yarn.util.Records; + +/** + *

+ * ResourceUtilization models a set of computer resource + * utilization in the cluster. + *

+ * + *

+ * Currently it models both memory and CPU. + *

+ * + *

+ * The unit for memory is megabytes. CPU is modeled with virtual cores (vcores), + * a unit for expressing parallelism. + *

+ * + * @see Resource + */ +@Public +@Stable +public abstract class ResourceUtilization implements + Comparable { + @Public + @Stable + public static ResourceUtilization newInstance(int memory, int milliVCores) { + ResourceUtilization resource = Records.newRecord(ResourceUtilization.class); + resource.setMemory(memory); + resource.setMilliVirtualCores(milliVCores); + return resource; + } + + /** + * Get memory of the resource utilization. + * + * @return memory of the resource utilization + */ + @Public + @Stable + public abstract int getMemory(); + + /** + * Set memory of the resource utilization. + * + * @param memory memory of the resource utilization + */ + @Public + @Stable + public abstract void setMemory(int memory); + + /** + * Get number of virtual cpu cores of the resource utilization. + * + * Virtual cores are a unit for expressing CPU parallelism. + * + * @return num of virtual cpu cores of the resource utilization + */ + @Public + @Evolving + public abstract int getMilliVirtualCores(); + + /** + * Set number of virtual cpu cores of the resource. + * + * Virtual cores are a unit for expressing CPU parallelism. + * + * @param vCores number of virtual cpu cores of the resource + * utilization + */ + @Public + @Evolving + public abstract void setMilliVirtualCores(int milliVCores); + + @Override + public int hashCode() { + final int prime = 263167; + int result = 3571; + result = 939769357 + getMemory(); // prime * result = 939769357 initially + result = prime * result + getMilliVirtualCores(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ResourceUtilization)) { + return false; + } + ResourceUtilization other = (ResourceUtilization) obj; + if (getMemory() != other.getMemory() + || getMilliVirtualCores() != other.getMilliVirtualCores()) { + return false; + } + return true; + } + + @Override + public String toString() { + return ""; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_protos.proto b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_protos.proto index b9969b0..293b71e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_protos.proto +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_protos.proto @@ -58,6 +58,11 @@ message ResourceProto { optional int32 virtual_cores = 2; } +message ResourceUtilizationProto { + optional int32 memory = 1; + optional int32 milli_virtual_cores = 2; +} + message ResourceOptionProto { optional ResourceProto resource = 1; optional int32 over_commit_timeout = 2; @@ -455,6 +460,7 @@ message ContainerStatusProto { optional ContainerStateProto state = 2; optional string diagnostics = 3 [default = "N/A"]; optional int32 exit_status = 4 [default = -1000]; + optional ResourceUtilizationProto utilization = 5; } enum ContainerExitStatusProto { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ContainerStatusPBImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ContainerStatusPBImpl.java index 86f2af9..46a5f21 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ContainerStatusPBImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ContainerStatusPBImpl.java @@ -24,10 +24,12 @@ import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerState; import org.apache.hadoop.yarn.api.records.ContainerStatus; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.proto.YarnProtos.ContainerIdProto; import org.apache.hadoop.yarn.proto.YarnProtos.ContainerStateProto; import org.apache.hadoop.yarn.proto.YarnProtos.ContainerStatusProto; import org.apache.hadoop.yarn.proto.YarnProtos.ContainerStatusProtoOrBuilder; +import org.apache.hadoop.yarn.proto.YarnProtos.ResourceUtilizationProto; import com.google.protobuf.TextFormat; @@ -168,6 +170,25 @@ public synchronized void setDiagnostics(String diagnostics) { builder.setDiagnostics(diagnostics); } + @Override + public synchronized ResourceUtilization getUtilization() { + ContainerStatusProtoOrBuilder p = viaProto ? proto : builder; + if (!p.hasUtilization()) { + return null; + } + return convertFromProtoFormat(p.getUtilization()); + } + + @Override + public synchronized void setUtilization(ResourceUtilization utilization) { + maybeInitBuilder(); + if (utilization == null) { + builder.clearUtilization(); + return; + } + builder.setUtilization(convertToProtoFormat(utilization)); + } + private ContainerStateProto convertToProtoFormat(ContainerState e) { return ProtoUtils.convertToProtoFormat(e); } @@ -184,6 +205,12 @@ private ContainerIdProto convertToProtoFormat(ContainerId t) { return ((ContainerIdPBImpl)t).getProto(); } + private ResourceUtilizationProto convertToProtoFormat(ResourceUtilization r) { + return ((ResourceUtilizationPBImpl) r).getProto(); + } - -} + private ResourceUtilizationPBImpl convertFromProtoFormat( + ResourceUtilizationProto p) { + return new ResourceUtilizationPBImpl(p); + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ResourceUtilizationPBImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ResourceUtilizationPBImpl.java new file mode 100644 index 0000000..47591b1 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/records/impl/pb/ResourceUtilizationPBImpl.java @@ -0,0 +1,92 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.api.records.impl.pb; + + +import org.apache.hadoop.classification.InterfaceAudience.Private; +import org.apache.hadoop.classification.InterfaceStability.Unstable; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; +import org.apache.hadoop.yarn.proto.YarnProtos.ResourceUtilizationProto; +import org.apache.hadoop.yarn.proto.YarnProtos.ResourceUtilizationProtoOrBuilder; + +@Private +@Unstable +public class ResourceUtilizationPBImpl extends ResourceUtilization { + ResourceUtilizationProto proto = ResourceUtilizationProto + .getDefaultInstance(); + ResourceUtilizationProto.Builder builder = null; + boolean viaProto = false; + + public ResourceUtilizationPBImpl() { + builder = ResourceUtilizationProto.newBuilder(); + } + + public ResourceUtilizationPBImpl(ResourceUtilizationProto proto) { + this.proto = proto; + viaProto = true; + } + + public ResourceUtilizationProto getProto() { + proto = viaProto ? proto : builder.build(); + viaProto = true; + return proto; + } + + private void maybeInitBuilder() { + if (viaProto || builder == null) { + builder = ResourceUtilizationProto.newBuilder(proto); + } + viaProto = false; + } + + @Override + public int getMemory() { + ResourceUtilizationProtoOrBuilder p = viaProto ? proto : builder; + return (p.getMemory()); + } + + @Override + public void setMemory(int memory) { + maybeInitBuilder(); + builder.setMemory((memory)); + } + + @Override + public int getMilliVirtualCores() { + ResourceUtilizationProtoOrBuilder p = viaProto ? proto : builder; + return (p.getMilliVirtualCores()); + } + + @Override + public void setMilliVirtualCores(int milliVCores) { + maybeInitBuilder(); + builder.setMilliVirtualCores(milliVCores); + } + + @Override + public int compareTo(ResourceUtilization other) { + int diff = this.getMemory() - other.getMemory(); + if (diff == 0) { + diff = + Float.compare(this.getMilliVirtualCores(), + other.getMilliVirtualCores()); + } + return diff; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/Container.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/Container.java index 56b4fdd..c799323 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/Container.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/Container.java @@ -27,6 +27,7 @@ import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.security.ContainerTokenIdentifier; import org.apache.hadoop.yarn.server.api.protocolrecords.NMContainerStatus; @@ -37,6 +38,8 @@ Resource getResource(); + ResourceUtilization getUtilization(); + ContainerTokenIdentifier getContainerTokenIdentifier(); String getUser(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/ContainerImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/ContainerImpl.java index 9997ca2..cfc7d8b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/ContainerImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/ContainerImpl.java @@ -45,6 +45,7 @@ import org.apache.hadoop.yarn.api.records.LocalResource; import org.apache.hadoop.yarn.api.records.LocalResourceVisibility; import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.Dispatcher; import org.apache.hadoop.yarn.event.EventHandler; @@ -92,6 +93,7 @@ private final ContainerTokenIdentifier containerTokenIdentifier; private final ContainerId containerId; private final Resource resource; + private final ResourceUtilization utilization; private final String user; private int exitCode = ContainerExitStatus.INVALID; private final StringBuilder diagnostics; @@ -136,6 +138,7 @@ public ContainerImpl(Configuration conf, Dispatcher dispatcher, this.containerTokenIdentifier = containerTokenIdentifier; this.containerId = containerTokenIdentifier.getContainerID(); this.resource = containerTokenIdentifier.getResource(); + this.utilization = ResourceUtilization.newInstance(0, 0); this.diagnostics = new StringBuilder(); this.credentials = creds; this.metrics = metrics; @@ -455,6 +458,11 @@ public Resource getResource() { } @Override + public ResourceUtilization getUtilization() { + return this.utilization; + } + + @Override public ContainerTokenIdentifier getContainerTokenIdentifier() { this.readLock.lock(); try { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java index d1e5e01..183b37d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java @@ -32,11 +32,13 @@ import org.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix; import org.apache.hadoop.yarn.api.records.ContainerExitStatus; import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.AsyncDispatcher; import org.apache.hadoop.yarn.event.Dispatcher; import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor; import org.apache.hadoop.yarn.server.nodemanager.Context; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerKillEvent; import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerHardwareUtils; import org.apache.hadoop.yarn.util.ResourceCalculatorProcessTree; @@ -466,6 +468,18 @@ public void run() { currentPmemUsage, pmemLimit)); } + // Save utilization for this container + Container container = context.getContainers().get(containerId); + ResourceUtilization containerUtilization = + container.getUtilization(); + containerUtilization.setMemory((int) (currentPmemUsage >> 20)); + containerUtilization.setMilliVirtualCores(milliVcoresUsed); + + if (LOG.isDebugEnabled()) { + LOG.debug("Container " + containerId + " utilization is " + + container.getUtilization()); + } + // Add usage to container metrics if (containerMetricsEnabled) { ContainerMetrics.forContainer( diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/MockContainer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/MockContainer.java index b2ccb61..8221953 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/MockContainer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/MockContainer.java @@ -32,6 +32,7 @@ import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.event.Dispatcher; import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; @@ -140,4 +141,9 @@ public ContainerTokenIdentifier getContainerTokenIdentifier() { public NMContainerStatus getNMContainerStatus() { return null; } + + @Override + public ResourceUtilization getUtilization() { + return null; + } }