Skip to content

Commit 1eb42e0

Browse files
committed
TEZ-2119: Counter for launched containers
1 parent 5038075 commit 1eb42e0

20 files changed

Lines changed: 483 additions & 95 deletions

tez-api/src/main/java/org/apache/tez/common/counters/DAGCounter.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,51 @@ public enum DAGCounter {
4141
AM_CPU_MILLISECONDS,
4242
/** Wall clock time taken by all the tasks. */
4343
WALL_CLOCK_MILLIS,
44-
AM_GC_TIME_MILLIS
44+
AM_GC_TIME_MILLIS,
45+
46+
/*
47+
* Type: # of containers
48+
* Both allocated and launched containers before DAG start.
49+
* This is incremented only once when the DAG starts and it's calculated
50+
* by querying all the held containers from TaskSchedulers.
51+
*/
52+
INITIAL_HELD_CONTAINERS,
53+
54+
/*
55+
* Type: # of containers
56+
* All containers that have been seen/used in this DAG by task allocation.
57+
* This counter can be calculated at the end of DAG by simply counting the distinct
58+
* ContainerIds that have been seen in TaskSchedulerManager.taskAllocated callbacks.
59+
*/
60+
TOTAL_CONTAINERS_USED,
61+
62+
/*
63+
* Type: # of events
64+
* Number of container allocations during a DAG. This is incremented every time
65+
* the containerAllocated callback is called in the TaskSchedulerContext.
66+
* This counter doesn't account for initially held (launched, allocated) containers.
67+
*/
68+
TOTAL_CONTAINER_ALLOCATION_COUNT,
69+
70+
/*
71+
* Type: # of events
72+
* Number of container launches during a DAG. This is incremented every time
73+
* the containerLaunched callback is called in the ContainerLauncherContext.
74+
* This counter doesn't account for initially held (launched, allocated) containers.
75+
*/
76+
TOTAL_CONTAINER_LAUNCH_COUNT,
77+
78+
/*
79+
* Type: # of events
80+
* Number of container releases during a DAG. This is incremented every time
81+
* the containerBeingReleased callback is called in the TaskSchedulerContext.
82+
*/
83+
TOTAL_CONTAINER_RELEASE_COUNT,
84+
85+
/*
86+
* Type: # of events
87+
* Number of container reuses during a DAG. This is incremented every time
88+
* the containerReused callback is called in the TaskSchedulerContext.
89+
*/
90+
TOTAL_CONTAINER_REUSE_COUNT
4591
}

tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskScheduler.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package org.apache.tez.serviceplugins.api;
1616

17+
import java.util.List;
18+
1719
import javax.annotation.Nullable;
1820

1921
import org.apache.hadoop.classification.InterfaceAudience;
@@ -263,4 +265,17 @@ public abstract boolean deallocateTask(Object task, boolean taskSucceeded,
263265
*/
264266
public abstract void dagComplete() throws ServicePluginException;
265267

268+
/**
269+
* Get the number of held containers.
270+
*/
271+
public abstract int getHeldContainersCount();
272+
273+
/**
274+
* Callback to be used in the event of a container allocation.
275+
*/
276+
protected void onContainersAllocated(List<Container> containers) {
277+
for (Container container : containers) {
278+
getContext().containerAllocated(container);
279+
}
280+
}
266281
}

tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskSchedulerContext.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ void taskAllocated(Object task,
8484
Object appCookie,
8585
Container container);
8686

87+
/**
88+
* Indicate to the framework that a container is being allocated.
89+
*
90+
* @param container the actual container
91+
*/
92+
void containerAllocated(Container container);
93+
94+
/**
95+
* Indicate to the framework that a container is being reused:
96+
* there is a task assigned to an already used container.
97+
*
98+
* @param container the actual container
99+
*/
100+
void containerReused(Container container);
87101

88102
/**
89103
* Indicate to the framework that a container has completed. This is typically used by sources

tez-dag/src/main/java/org/apache/tez/dag/app/ContainerLauncherContextImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
2222
import org.apache.hadoop.yarn.api.records.ContainerId;
2323
import org.apache.tez.common.TezUtilsInternal;
24+
import org.apache.tez.common.counters.DAGCounter;
2425
import org.apache.tez.dag.api.UserPayload;
2526
import org.apache.tez.dag.app.dag.event.DAGAppMasterEventType;
2627
import org.apache.tez.dag.app.dag.event.DAGAppMasterEventUserServiceFatalError;
@@ -65,13 +66,13 @@ public ContainerLauncherContextImpl(AppContext appContext, ContainerLauncherMana
6566

6667
@Override
6768
public void containerLaunched(ContainerId containerId) {
69+
context.getCurrentDAG().incrementDagCounter(DAGCounter.TOTAL_CONTAINER_LAUNCH_COUNT, 1);
6870
context.getEventHandler().handle(
6971
new AMContainerEventLaunched(containerId));
7072
ContainerLaunchedEvent lEvt = new ContainerLaunchedEvent(
7173
containerId, context.getClock().getTime(), context.getApplicationAttemptId());
7274
context.getHistoryHandler().handle(new DAGHistoryEvent(
7375
null, lEvt));
74-
7576
}
7677

7778
@Override

tez-dag/src/main/java/org/apache/tez/dag/app/DAGAppMaster.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
import org.apache.tez.common.TezConverterUtils;
122122
import org.apache.tez.common.TezUtilsInternal;
123123
import org.apache.tez.common.VersionInfo;
124+
import org.apache.tez.common.counters.DAGCounter;
124125
import org.apache.tez.common.counters.Limits;
125126
import org.apache.tez.common.security.ACLManager;
126127
import org.apache.tez.common.security.JobTokenIdentifier;
@@ -772,7 +773,8 @@ protected synchronized void handle(DAGAppMasterEvent event) {
772773
System.err.println(timeStamp + " Completed Dag: " + finishEvt.getDAGId());
773774
System.out.println(timeStamp + " Completed Dag: " + finishEvt.getDAGId());
774775
// Stop vertex services if any
775-
stopVertexServices(currentDAG);
776+
currentDAG.onFinish();
777+
776778
if (!isSession) {
777779
LOG.info("Not a session, AM will unregister as DAG has completed");
778780
this.taskSchedulerManager.setShouldUnregisterFlag();
@@ -1900,7 +1902,7 @@ void stopServices() {
19001902
Exception firstException = null;
19011903
// stop in reverse order of start
19021904
if (currentDAG != null) {
1903-
stopVertexServices(currentDAG);
1905+
currentDAG.onFinish();
19041906
}
19051907
List<Service> serviceList = new ArrayList<Service>(services.size());
19061908
for (ServiceWithDependency sd : services.values()) {
@@ -2090,7 +2092,7 @@ public void serviceStart() throws Exception {
20902092
dagEventDispatcher.handle(recoverDAGEvent);
20912093
// If we reach here, then we have recoverable DAG and we need to
20922094
// reinitialize the vertex services including speculators.
2093-
startVertexServices(currentDAG);
2095+
currentDAG.onStart();
20942096
this.state = DAGAppMasterState.RUNNING;
20952097
}
20962098
} else {
@@ -2557,21 +2559,15 @@ public Void run() throws Exception {
25572559
throw new TezUncheckedException(e);
25582560
}
25592561

2562+
countHeldContainers(newDAG);
25602563
startDAGExecution(newDAG, lrDiff);
25612564
// set state after curDag is set
25622565
this.state = DAGAppMasterState.RUNNING;
25632566
}
25642567

2565-
private void startVertexServices(DAG dag) {
2566-
for (Vertex v : dag.getVertices().values()) {
2567-
v.startServices();
2568-
}
2569-
}
2570-
2571-
void stopVertexServices(DAG dag) {
2572-
for (Vertex v: dag.getVertices().values()) {
2573-
v.stopServices();
2574-
}
2568+
private void countHeldContainers(DAG newDAG) {
2569+
newDAG.setDagCounter(DAGCounter.INITIAL_HELD_CONTAINERS,
2570+
taskSchedulerManager.getHeldContainersCount());
25752571
}
25762572

25772573
private void startDAGExecution(DAG dag, final Map<String, LocalResource> additionalAmResources)
@@ -2606,7 +2602,7 @@ public List<URL> run() throws Exception {
26062602
// job-init to be done completely here.
26072603
dagEventDispatcher.handle(initDagEvent);
26082604
// Start the vertex services
2609-
startVertexServices(dag);
2605+
dag.onStart();
26102606
// All components have started, start the job.
26112607
/** create a job-start event to get this ball rolling */
26122608
DAGEvent startDagEvent = new DAGEventStartDag(currentDAG.getID(), additionalUrlsForClasspath);

tez-dag/src/main/java/org/apache/tez/dag/app/dag/DAG.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import java.util.Set;
2424

2525
import org.apache.hadoop.security.UserGroupInformation;
26+
import org.apache.hadoop.yarn.api.records.ContainerId;
2627
import org.apache.hadoop.yarn.api.records.LocalResource;
2728
import org.apache.hadoop.yarn.event.EventHandler;
29+
import org.apache.tez.common.counters.DAGCounter;
2830
import org.apache.tez.common.counters.TezCounters;
2931
import org.apache.tez.dag.api.TezException;
3032
import org.apache.tez.dag.api.client.DAGStatusBuilder;
@@ -102,4 +104,18 @@ VertexStatusBuilder getVertexStatus(String vertexName,
102104
*/
103105
@Nullable DAGScheduler getDAGScheduler();
104106

107+
void incrementDagCounter(DAGCounter counter, int incrValue);
108+
void setDagCounter(DAGCounter counter, int setValue);
109+
void addUsedContainer(ContainerId containerId);
110+
111+
/**
112+
* Called by the DAGAppMaster when the DAG is started normally or in the event of recovery.
113+
*/
114+
void onStart();
115+
116+
/**
117+
* Called by the DAGAppMaster when the DAG is finished, or there is a currentDAG on AM stop.
118+
* The implementation of this method should be idempontent.
119+
*/
120+
void onFinish();
105121
}

tez-dag/src/main/java/org/apache/tez/dag/app/dag/impl/DAGImpl.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.apache.hadoop.security.Credentials;
6262
import org.apache.hadoop.security.UserGroupInformation;
6363
import org.apache.hadoop.yarn.api.ApplicationConstants;
64+
import org.apache.hadoop.yarn.api.records.ContainerId;
6465
import org.apache.hadoop.yarn.api.records.LocalResource;
6566
import org.apache.hadoop.yarn.event.EventHandler;
6667
import org.apache.hadoop.yarn.state.InvalidStateTransitonException;
@@ -248,6 +249,7 @@ public class DAGImpl implements org.apache.tez.dag.app.dag.DAG,
248249
new CommitCompletedTransition();
249250

250251
private final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
252+
private final Set<ContainerId> containersUsedByCurrentDAG = new HashSet<>();
251253

252254
protected static final
253255
StateMachineFactory<DAGImpl, DAGState, DAGEventType, DAGEvent>
@@ -1441,6 +1443,16 @@ private void updateCpuCounters() {
14411443
dagCounters.findCounter(DAGCounter.AM_GC_TIME_MILLIS).setValue(totalDAGGCTime);
14421444
}
14431445

1446+
@Override
1447+
public void incrementDagCounter(DAGCounter counter, int incrValue) {
1448+
dagCounters.findCounter(counter).increment(incrValue);
1449+
}
1450+
1451+
@Override
1452+
public void setDagCounter(DAGCounter counter, int setValue) {
1453+
dagCounters.findCounter(counter).setValue(setValue);
1454+
}
1455+
14441456
private DAGState finished(DAGState finalState) {
14451457
boolean dagError = false;
14461458
try {
@@ -2542,4 +2554,36 @@ public DAGImpl setLogDirs(String[] logDirs) {
25422554
this.logDirs = logDirs;
25432555
return this;
25442556
}
2557+
2558+
@Override
2559+
public void onStart() {
2560+
startVertexServices();
2561+
}
2562+
2563+
@Override
2564+
public void onFinish() {
2565+
stopVertexServices();
2566+
handleUsedContainersOnDagFinish();
2567+
}
2568+
2569+
private void startVertexServices() {
2570+
for (Vertex v : getVertices().values()) {
2571+
v.startServices();
2572+
}
2573+
}
2574+
2575+
void stopVertexServices() {
2576+
for (Vertex v : getVertices().values()) {
2577+
v.stopServices();
2578+
}
2579+
}
2580+
2581+
@Override
2582+
public void addUsedContainer(ContainerId containerId) {
2583+
containersUsedByCurrentDAG.add(containerId);
2584+
}
2585+
2586+
private void handleUsedContainersOnDagFinish() {
2587+
setDagCounter(DAGCounter.TOTAL_CONTAINERS_USED, containersUsedByCurrentDAG.size());
2588+
}
25452589
}

tez-dag/src/main/java/org/apache/tez/dag/app/rm/DagAwareYarnTaskScheduler.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ public void shutdown() throws Exception {
328328

329329
@Override
330330
public void onContainersAllocated(List<Container> containers) {
331+
super.onContainersAllocated(containers);
332+
331333
AMState appState = getContext().getAMState();
332334
if (stopRequested || appState == AMState.COMPLETED) {
333335
LOG.info("Ignoring {} allocations since app is terminating", containers.size());
@@ -946,6 +948,9 @@ private void addTaskAssignment(TaskRequest request, HeldContainer hc) {
946948
assignedVertices.set(vertexIndex);
947949
}
948950
cset.add(hc);
951+
if (!hc.isNew()) {
952+
getContext().containerReused(hc.getContainer());
953+
}
949954
hc.assignTask(request);
950955
}
951956

@@ -1489,6 +1494,10 @@ Object getLastTask() {
14891494
return lastRequest != null ? lastRequest.getTask() : null;
14901495
}
14911496

1497+
boolean isNew() {
1498+
return lastRequest == null;
1499+
}
1500+
14921501
String getMatchingLocation() {
14931502
switch (state) {
14941503
case MATCHING_LOCAL:
@@ -2089,4 +2098,9 @@ protected void afterExecute(Runnable r, Throwable t) {
20892098
}
20902099
}
20912100
}
2101+
2102+
@Override
2103+
public int getHeldContainersCount() {
2104+
return heldContainers.size();
2105+
}
20922106
}

tez-dag/src/main/java/org/apache/tez/dag/app/rm/LocalTaskSchedulerService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,4 +513,9 @@ void preemptTask(DeallocateContainerRequest request) {
513513
}
514514
}
515515
}
516+
517+
@Override
518+
public int getHeldContainersCount() {
519+
return 0;
520+
}
516521
}

tez-dag/src/main/java/org/apache/tez/dag/app/rm/TaskSchedulerContextImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.hadoop.yarn.api.records.NodeReport;
2929
import org.apache.hadoop.yarn.api.records.Resource;
3030
import org.apache.tez.common.ContainerSignatureMatcher;
31+
import org.apache.tez.common.counters.DAGCounter;
3132
import org.apache.tez.dag.api.TezUncheckedException;
3233
import org.apache.tez.dag.api.UserPayload;
3334
import org.apache.tez.dag.app.AppContext;
@@ -69,13 +70,24 @@ public void taskAllocated(Object task, Object appCookie, Container container) {
6970
taskSchedulerManager.taskAllocated(schedulerId, task, appCookie, container);
7071
}
7172

73+
@Override
74+
public void containerAllocated(Container container) {
75+
appContext.getCurrentDAG().incrementDagCounter(DAGCounter.TOTAL_CONTAINER_ALLOCATION_COUNT, 1);
76+
}
77+
78+
@Override
79+
public void containerReused(Container container) {
80+
appContext.getCurrentDAG().incrementDagCounter(DAGCounter.TOTAL_CONTAINER_REUSE_COUNT, 1);
81+
}
82+
7283
@Override
7384
public void containerCompleted(Object taskLastAllocated, ContainerStatus containerStatus) {
7485
taskSchedulerManager.containerCompleted(schedulerId, taskLastAllocated, containerStatus);
7586
}
7687

7788
@Override
7889
public void containerBeingReleased(ContainerId containerId) {
90+
appContext.getCurrentDAG().incrementDagCounter(DAGCounter.TOTAL_CONTAINER_RELEASE_COUNT, 1);
7991
taskSchedulerManager.containerBeingReleased(schedulerId, containerId);
8092
}
8193

0 commit comments

Comments
 (0)