timing.ui: make Aggregated functions merge statistics
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.core / src / org / eclipse / tracecompass / internal / analysis / timing / core / callgraph / AggregatedCalledFunction.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10 package org.eclipse.tracecompass.internal.analysis.timing.core.callgraph;
11
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.eclipse.tracecompass.common.core.NonNullUtils;
18
19 /**
20 * This class represents a function call in a certain level in the call stack.
21 * It's used to build an aggregation segment tree (aggregated by depth and
22 * callers). Per example,the two calls to the function A() in the call graph
23 * below will be combined into one node in the generated tree:
24 *
25 * <pre>
26 * (Depth=0) main main
27 * ↓↑ ↓↑ ↓↑ => ↓↑ ↓↑
28 * (Depth=1) A() B() A() A() B()
29 * </pre>
30 *
31 * @author Sonia Farrah
32 *
33 */
34 public class AggregatedCalledFunction {
35
36 // ------------------------------------------------------------------------
37 // Attributes
38 // ------------------------------------------------------------------------
39
40 private final Object fSymbol;
41 private final int fDepth;
42 private final int fMaxDepth;
43 private final Map<Object, AggregatedCalledFunction> fChildren = new HashMap<>();
44 private final @Nullable AggregatedCalledFunction fParent;
45 private final AggregatedCalledFunctionStatistics fStatistics;
46 private long fDuration;
47 private long fSelfTime;
48 private final int fProcessId;
49
50 /**
51 * Constructor, parent is not null
52 *
53 * @param calledFunction
54 * called function
55 * @param parent
56 * the parent entry
57 *
58 */
59 public AggregatedCalledFunction(AbstractCalledFunction calledFunction, AggregatedCalledFunction parent) {
60 fSymbol = calledFunction.getSymbol();
61 fDuration = calledFunction.getLength();
62 fSelfTime = calledFunction.getLength();
63 fDepth = calledFunction.getDepth();
64 fProcessId = calledFunction.getProcessId();
65 fMaxDepth = parent.getMaxDepth();
66 fParent = parent;
67 fStatistics = new AggregatedCalledFunctionStatistics(calledFunction, calledFunction);
68 }
69
70 /**
71 * Root constructor, parent is null
72 *
73 * @param calledFunction
74 * the called function
75 * @param maxDepth
76 * the maximum depth
77 */
78 public AggregatedCalledFunction(AbstractCalledFunction calledFunction, int maxDepth) {
79 fSymbol = calledFunction.getSymbol();
80 fDuration = calledFunction.getLength();
81 fSelfTime = calledFunction.getLength();
82 fDepth = calledFunction.getDepth();
83 fProcessId = calledFunction.getProcessId();
84 fMaxDepth = maxDepth;
85 fParent = null;
86 fStatistics = new AggregatedCalledFunctionStatistics(calledFunction, calledFunction);
87 }
88
89 /**
90 * The function's symbol (address or name)
91 *
92 * @return The function's symbol
93 */
94 public Object getSymbol() {
95 return fSymbol;
96 }
97
98 /**
99 * The callees of the function
100 *
101 * @return The function's callees
102 */
103 public synchronized Collection<AggregatedCalledFunction> getChildren() {
104 return fChildren.values();
105 }
106
107 /**
108 * The function's caller
109 *
110 * @return The caller of a function
111 */
112 public @Nullable AggregatedCalledFunction getParent() {
113 return fParent;
114 }
115
116 /**
117 * Add a new callee into the Callees list. If the function exists in the
118 * callees list, the new callee's duration will be added to its duration and
119 * it'll combine their callees.
120 *
121 * @param child
122 * The callees of a function
123 */
124 public synchronized void addChild(AggregatedCalledFunction child) {
125 AggregatedCalledFunction node = fChildren.get(child.getSymbol());
126 if (node == null) {
127 fChildren.put(child.getSymbol(), child);
128 } else {
129 merge(node, child);
130 fChildren.replace(node.getSymbol(), node);
131 }
132 fSelfTime -= child.fDuration;
133 fStatistics.initializeMaxMinSelfTime(fSelfTime);
134 }
135
136 /**
137 * Modify the function's duration
138 *
139 * @param duration
140 * The amount to increment the duration by
141 */
142 private void addToDuration(long duration) {
143 fDuration += duration;
144 }
145
146 /**
147 * Merge the callees of two functions.
148 *
149 * @param firstNode
150 * The first parent secondNode The second parent
151 */
152 private static void mergeChildren(AggregatedCalledFunction firstNode, AggregatedCalledFunction secondNode) {
153 for (Map.Entry<Object, AggregatedCalledFunction> FunctionEntry : secondNode.fChildren.entrySet()) {
154 Object childSymbol = NonNullUtils.checkNotNull(FunctionEntry.getKey());
155 AggregatedCalledFunction secondNodeChild = NonNullUtils.checkNotNull(FunctionEntry.getValue());
156 AggregatedCalledFunction aggregatedCalledFunction = firstNode.fChildren.get(childSymbol);
157 if (aggregatedCalledFunction == null) {
158 firstNode.fChildren.put(secondNodeChild.getSymbol(), secondNodeChild);
159 } else {
160 // combine children
161 AggregatedCalledFunction firstNodeChild = aggregatedCalledFunction;
162 merge(firstNodeChild, secondNodeChild);
163 firstNode.fChildren.replace(firstNodeChild.getSymbol(), firstNodeChild);
164 }
165 }
166 }
167
168 /**
169 * Merge two functions, add durations, self times, increment the calls,
170 * update statistics and merge children.
171 *
172 * @param destination
173 * the node to merge to
174 * @param source
175 * the node to merge
176 */
177 private static void merge(AggregatedCalledFunction destination, AggregatedCalledFunction source) {
178 long sourceDuration = source.getDuration();
179 long sourceSelfTime = source.getSelfTime();
180 destination.addToDuration(sourceDuration);
181 destination.addToSelfTime(sourceSelfTime);
182 destination.getFunctionStatistics().update(source.getFunctionStatistics(), sourceDuration, sourceSelfTime);
183 // merge the children callees.
184 mergeChildren(destination, source);
185 }
186
187 /**
188 * The function's duration
189 *
190 * @return The duration of the function
191 */
192 public long getDuration() {
193 return fDuration;
194 }
195
196 /**
197 * The function's depth
198 *
199 * @return The depth of the function
200 */
201 public int getDepth() {
202 return fDepth;
203 }
204
205 /**
206 * The depth of the aggregated tree
207 *
208 * @return The depth of the aggregated tree
209 */
210 public int getMaxDepth() {
211 return fMaxDepth;
212 }
213
214 /**
215 * The number of calls of a function
216 *
217 * @return The number of calls of a function
218 */
219 public long getNbCalls() {
220 return fStatistics.getNbSegments();
221 }
222
223 /**
224 * The self time of an aggregated function
225 *
226 * @return The self time
227 */
228 public long getSelfTime() {
229 return fSelfTime;
230 }
231
232 /**
233 * Add to the self time of an aggregated function
234 *
235 * @param selfTime
236 * The amount of self time to add
237 */
238 public void addToSelfTime(long selfTime) {
239 fSelfTime += selfTime;
240 }
241
242 /**
243 * The process ID of the trace application.
244 * @return The process Id
245 */
246 public int getProcessId() {
247 return fProcessId;
248 }
249
250 /**
251 * Returns whether the function has callees.
252 *
253 * @return Boolean
254 */
255 public Boolean hasChildren() {
256 return !fChildren.isEmpty();
257 }
258
259 /**
260 * The function's statistics
261 *
262 * @return The function's statistics
263 */
264 public AggregatedCalledFunctionStatistics getFunctionStatistics() {
265 return fStatistics;
266 }
267 }
This page took 0.036744 seconds and 5 git commands to generate.