• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.traceview;
18 
19 import org.eclipse.swt.graphics.Color;
20 import org.eclipse.swt.graphics.Image;
21 
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 
28 public class MethodData {
29 
30     private int mId;
31     private int mRank = -1;
32     private String mClassName;
33     private String mMethodName;
34     private String mSignature;
35     private String mName;
36     private String mProfileName;
37     private String mPathname;
38     private int mLineNumber;
39     private long mElapsedExclusive;
40     private long mElapsedInclusive;
41     private long mTopExclusive;
42     private int[] mNumCalls = new int[2]; // index 0=normal, 1=recursive
43     private Color mColor;
44     private Color mFadedColor;
45     private Image mImage;
46     private Image mFadedImage;
47     private HashMap<Integer, ProfileData> mParents;
48     private HashMap<Integer, ProfileData> mChildren;
49 
50     // The parents of this method when this method was in a recursive call
51     private HashMap<Integer, ProfileData> mRecursiveParents;
52 
53     // The children of this method when this method was in a recursive call
54     private HashMap<Integer, ProfileData> mRecursiveChildren;
55 
56     private ProfileNode[] mProfileNodes;
57     private int mX;
58     private int mY;
59     private double mWeight;
60 
MethodData(int id, String className)61     public MethodData(int id, String className) {
62         mId = id;
63         mClassName = className;
64         mMethodName = null;
65         mSignature = null;
66         mPathname = null;
67         mLineNumber = -1;
68         computeName();
69         computeProfileName();
70     }
71 
MethodData(int id, String className, String methodName, String signature, String pathname, int lineNumber)72     public MethodData(int id, String className, String methodName,
73             String signature, String pathname, int lineNumber) {
74         mId = id;
75         mClassName = className;
76         mMethodName = methodName;
77         mSignature = signature;
78         mPathname = pathname;
79         mLineNumber = lineNumber;
80         computeName();
81         computeProfileName();
82     }
83 
84     private Comparator<ProfileData> mByElapsedInclusive = new Comparator<ProfileData>() {
85         public int compare(ProfileData pd1, ProfileData pd2) {
86             if (pd2.getElapsedInclusive() > pd1.getElapsedInclusive())
87                 return 1;
88             if (pd2.getElapsedInclusive() < pd1.getElapsedInclusive())
89                 return -1;
90             return 0;
91         }
92     };
93 
addWeight(int x, int y, double weight)94     public double addWeight(int x, int y, double weight) {
95         if (mX == x && mY == y)
96             mWeight += weight;
97         else {
98             mX = x;
99             mY = y;
100             mWeight = weight;
101         }
102         return mWeight;
103     }
104 
clearWeight()105     public void clearWeight() {
106         mWeight = 0;
107     }
108 
getRank()109     public int getRank() {
110         return mRank;
111     }
112 
setRank(int rank)113     public void setRank(int rank) {
114         mRank = rank;
115         computeProfileName();
116     }
117 
addElapsedExclusive(long time)118     public void addElapsedExclusive(long time) {
119         mElapsedExclusive += time;
120     }
121 
addElapsedInclusive(long time, boolean isRecursive, Call parent)122     public void addElapsedInclusive(long time, boolean isRecursive, Call parent) {
123         if (isRecursive == false) {
124             mElapsedInclusive += time;
125             mNumCalls[0] += 1;
126         } else {
127             mNumCalls[1] += 1;
128         }
129 
130         if (parent == null)
131             return;
132 
133         // Find the child method in the parent
134         MethodData parentMethod = parent.mMethodData;
135         if (parent.isRecursive()) {
136             parentMethod.mRecursiveChildren = updateInclusive(time,
137                     parentMethod, this, false,
138                     parentMethod.mRecursiveChildren);
139         } else {
140             parentMethod.mChildren = updateInclusive(time,
141                     parentMethod, this, false, parentMethod.mChildren);
142         }
143 
144         // Find the parent method in the child
145         if (isRecursive) {
146             mRecursiveParents = updateInclusive(time, this, parentMethod, true,
147                     mRecursiveParents);
148         } else {
149             mParents = updateInclusive(time, this, parentMethod, true,
150                     mParents);
151         }
152     }
153 
updateInclusive(long time, MethodData contextMethod, MethodData elementMethod, boolean elementIsParent, HashMap<Integer, ProfileData> map)154     private HashMap<Integer, ProfileData> updateInclusive(long time,
155             MethodData contextMethod, MethodData elementMethod,
156             boolean elementIsParent, HashMap<Integer, ProfileData> map) {
157         if (map == null) {
158             map = new HashMap<Integer, ProfileData>(4);
159         } else {
160             ProfileData profileData = map.get(elementMethod.mId);
161             if (profileData != null) {
162                 profileData.addElapsedInclusive(time);
163                 return map;
164             }
165         }
166 
167         ProfileData elementData = new ProfileData(contextMethod,
168                 elementMethod, elementIsParent);
169         elementData.setElapsedInclusive(time);
170         elementData.setNumCalls(1);
171         map.put(elementMethod.mId, elementData);
172         return map;
173     }
174 
analyzeData()175     public void analyzeData() {
176         // Sort the parents and children into decreasing inclusive time
177         ProfileData[] sortedParents;
178         ProfileData[] sortedChildren;
179         ProfileData[] sortedRecursiveParents;
180         ProfileData[] sortedRecursiveChildren;
181 
182         sortedParents = sortProfileData(mParents);
183         sortedChildren = sortProfileData(mChildren);
184         sortedRecursiveParents = sortProfileData(mRecursiveParents);
185         sortedRecursiveChildren = sortProfileData(mRecursiveChildren);
186 
187         // Add "self" time to the top of the sorted children
188         sortedChildren = addSelf(sortedChildren);
189 
190         // Create the ProfileNode objects that we need
191         ArrayList<ProfileNode> nodes = new ArrayList<ProfileNode>();
192         ProfileNode profileNode;
193         if (mParents != null) {
194             profileNode = new ProfileNode("Parents", this, sortedParents,
195                     true, false);
196             nodes.add(profileNode);
197         }
198         if (mChildren != null) {
199             profileNode = new ProfileNode("Children", this, sortedChildren,
200                     false, false);
201             nodes.add(profileNode);
202         }
203         if (mRecursiveParents!= null) {
204             profileNode = new ProfileNode("Parents while recursive", this,
205                     sortedRecursiveParents, true, true);
206             nodes.add(profileNode);
207         }
208         if (mRecursiveChildren != null) {
209             profileNode = new ProfileNode("Children while recursive", this,
210                     sortedRecursiveChildren, false, true);
211             nodes.add(profileNode);
212         }
213         mProfileNodes = nodes.toArray(new ProfileNode[nodes.size()]);
214     }
215 
216     // Create and return a ProfileData[] array that is a sorted copy
217     // of the given HashMap values.
sortProfileData(HashMap<Integer, ProfileData> map)218     private ProfileData[] sortProfileData(HashMap<Integer, ProfileData> map) {
219         if (map == null)
220             return null;
221 
222         // Convert the hash values to an array of ProfileData
223         Collection<ProfileData> values = map.values();
224         ProfileData[] sorted = values.toArray(new ProfileData[values.size()]);
225 
226         // Sort the array by elapsed inclusive time
227         Arrays.sort(sorted, mByElapsedInclusive);
228         return sorted;
229     }
230 
addSelf(ProfileData[] children)231     private ProfileData[] addSelf(ProfileData[] children) {
232         ProfileData[] pdata;
233         if (children == null) {
234             pdata = new ProfileData[1];
235         } else {
236             pdata = new ProfileData[children.length + 1];
237             System.arraycopy(children, 0, pdata, 1, children.length);
238         }
239         pdata[0] = new ProfileSelf(this);
240         return pdata;
241     }
242 
addTopExclusive(long time)243     public void addTopExclusive(long time) {
244         mTopExclusive += time;
245     }
246 
getTopExclusive()247     public long getTopExclusive() {
248         return mTopExclusive;
249     }
250 
getId()251     public int getId() {
252         return mId;
253     }
254 
computeName()255     private void computeName() {
256         if (mMethodName == null) {
257             mName = mClassName;
258             return;
259         }
260 
261         StringBuilder sb = new StringBuilder();
262         sb.append(mClassName);
263         sb.append(".");  //$NON-NLS-1$
264         sb.append(mMethodName);
265         sb.append(" ");  //$NON-NLS-1$
266         sb.append(mSignature);
267         mName = sb.toString();
268     }
269 
getName()270     public String getName() {
271         return mName;
272     }
273 
getClassName()274     public String getClassName() {
275         return mClassName;
276     }
277 
getMethodName()278     public String getMethodName() {
279         return mMethodName;
280     }
281 
getProfileName()282     public String getProfileName() {
283         return mProfileName;
284     }
285 
computeProfileName()286     public void computeProfileName() {
287         if (mRank == -1) {
288             mProfileName = mName;
289             return;
290         }
291 
292         StringBuilder sb = new StringBuilder();
293         sb.append(mRank);
294         sb.append(" ");  //$NON-NLS-1$
295         sb.append(getName());
296         mProfileName = sb.toString();
297     }
298 
getCalls()299     public String getCalls() {
300         return String.format("%d+%d", mNumCalls[0], mNumCalls[1]);
301     }
302 
getTotalCalls()303     public int getTotalCalls() {
304         return mNumCalls[0] + mNumCalls[1];
305     }
306 
getColor()307     public Color getColor() {
308         return mColor;
309     }
310 
setColor(Color color)311     public void setColor(Color color) {
312         mColor = color;
313     }
314 
setImage(Image image)315     public void setImage(Image image) {
316         mImage = image;
317     }
318 
getImage()319     public Image getImage() {
320         return mImage;
321     }
322 
323     @Override
toString()324     public String toString() {
325         return getName();
326     }
327 
getElapsedExclusive()328     public long getElapsedExclusive() {
329         return mElapsedExclusive;
330     }
331 
getElapsedInclusive()332     public long getElapsedInclusive() {
333         return mElapsedInclusive;
334     }
335 
setFadedColor(Color fadedColor)336     public void setFadedColor(Color fadedColor) {
337         mFadedColor = fadedColor;
338     }
339 
getFadedColor()340     public Color getFadedColor() {
341         return mFadedColor;
342     }
343 
setFadedImage(Image fadedImage)344     public void setFadedImage(Image fadedImage) {
345         mFadedImage = fadedImage;
346     }
347 
getFadedImage()348     public Image getFadedImage() {
349         return mFadedImage;
350     }
351 
setPathname(String pathname)352     public void setPathname(String pathname) {
353         mPathname = pathname;
354     }
355 
getPathname()356     public String getPathname() {
357         return mPathname;
358     }
359 
setLineNumber(int lineNumber)360     public void setLineNumber(int lineNumber) {
361         mLineNumber = lineNumber;
362     }
363 
getLineNumber()364     public int getLineNumber() {
365         return mLineNumber;
366     }
367 
getProfileNodes()368     public ProfileNode[] getProfileNodes() {
369         return mProfileNodes;
370     }
371 
372     public static class Sorter implements Comparator<MethodData> {
compare(MethodData md1, MethodData md2)373         public int compare(MethodData md1, MethodData md2) {
374             if (mColumn == Column.BY_NAME) {
375                 int result = md1.getName().compareTo(md2.getName());
376                 return (mDirection == Direction.INCREASING) ? result : -result;
377             }
378             if (mColumn == Column.BY_INCLUSIVE) {
379                 if (md2.getElapsedInclusive() > md1.getElapsedInclusive())
380                     return (mDirection == Direction.INCREASING) ? -1 : 1;
381                 if (md2.getElapsedInclusive() < md1.getElapsedInclusive())
382                     return (mDirection == Direction.INCREASING) ? 1 : -1;
383                 return md1.getName().compareTo(md2.getName());
384             }
385             if (mColumn == Column.BY_EXCLUSIVE) {
386                 if (md2.getElapsedExclusive() > md1.getElapsedExclusive())
387                     return (mDirection == Direction.INCREASING) ? -1 : 1;
388                 if (md2.getElapsedExclusive() < md1.getElapsedExclusive())
389                     return (mDirection == Direction.INCREASING) ? 1 : -1;
390                 return md1.getName().compareTo(md2.getName());
391             }
392             if (mColumn == Column.BY_CALLS) {
393                 int result = md1.getTotalCalls() - md2.getTotalCalls();
394                 if (result == 0)
395                     return md1.getName().compareTo(md2.getName());
396                 return (mDirection == Direction.INCREASING) ? result : -result;
397             }
398             if (mColumn == Column.BY_TIME_PER_CALL) {
399                 double time1 = md1.getElapsedInclusive();
400                 time1 = time1 / md1.getTotalCalls();
401                 double time2 = md2.getElapsedInclusive();
402                 time2 = time2 / md2.getTotalCalls();
403                 double diff = time1 - time2;
404                 int result = 0;
405                 if (diff < 0)
406                     result = -1;
407                 else if (diff > 0)
408                     result = 1;
409                 if (result == 0)
410                     return md1.getName().compareTo(md2.getName());
411                 return (mDirection == Direction.INCREASING) ? result : -result;
412             }
413             return 0;
414         }
415 
setColumn(Column column)416         public void setColumn(Column column) {
417             // If the sort column specified is the same as last time,
418             // then reverse the sort order.
419             if (mColumn == column) {
420                 // Reverse the sort order
421                 if (mDirection == Direction.INCREASING)
422                     mDirection = Direction.DECREASING;
423                 else
424                     mDirection = Direction.INCREASING;
425             } else {
426                 // Sort names into increasing order, data into decreasing order.
427                 if (column == Column.BY_NAME)
428                     mDirection = Direction.INCREASING;
429                 else
430                     mDirection = Direction.DECREASING;
431             }
432             mColumn = column;
433         }
434 
getColumn()435         public Column getColumn() {
436             return mColumn;
437         }
438 
setDirection(Direction direction)439         public void setDirection(Direction direction) {
440             mDirection = direction;
441         }
442 
getDirection()443         public Direction getDirection() {
444             return mDirection;
445         }
446 
447         public static enum Column {
448             BY_NAME, BY_EXCLUSIVE, BY_INCLUSIVE, BY_CALLS, BY_TIME_PER_CALL
449         };
450 
451         public static enum Direction {
452             INCREASING, DECREASING
453         };
454 
455         private Column mColumn;
456         private Direction mDirection;
457     }
458 }
459