Profilepublic class Profile extends Object
Fields Summary |
---|
Hashtable | nodesThis hashtable is a collection of all CallGraphNodes in the callgraph.
It's indexed by each CallGraphNode's index member, whose type
is Integer. | Hashtable | nodesByNameThis hashtable is a collection of all CallGraphNodes in the callgraph.
It's indexed by each CallGraphNodes's name, whose type is
String.
Each entry in this hashtable is either a CallGraphNodes (if only
one CallGraphNode of that name exists in the callgraph), or
a Vector (if two or more CallGraphNodes of that name exist in
the callgraph). | CallGraphNode | rootThe root of all call records. This root is artificially created.
It's the parent of all the parent-less CallGraphNode read from
a profile. | int | numParentsNumber of CallGraphNodes in this profile that has one or more children,
including this.root. | int | numFilesNumber of graph files to parse. | double | periodDuration (in msec) of the period when the profile data was collected. |
Constructors Summary |
---|
Profile(String[] files)
nodes = new Hashtable();
nodesByName = new Hashtable();
root = createTopNode(null, -1, "root");
numParents = 0;
numFiles = files.length;
if (isMultifile()) {
for (int i = 0; i < numFiles; i++) {
readInputFile(new FileParserContext(files[i], i + 1, this));
}
} else {
readInputFile(new FileParserContext(files[0], 0, this));
}
createCallGraph();
if (numParents > 0) {
root.endTime = period;
root.computeSummary();
}
root.computePercentage();
|
Methods Summary |
---|
void | addToIndexByName(CallGraphNode cgNode)Add this cgNode to the index of all CallGraphNodes by its name.
This index is maintained by the hashtable nodesByName
Object obj = nodesByName.get(cgNode.name);
//System.out.println(cgNode.name + "=" + obj);
if (obj == null) {
// Not in the table yet, store the cgNode itself
nodesByName.put(cgNode.name, cgNode);
}
else if (obj instanceof Vector) {
// Already has two more more cgNodes of the same name, append
// to the list
((Vector)obj).addElement(cgNode);
}
else {
// We've seen the second cgNode of the same name. Store both
// cgNodes inside a Vector and put that Vector in the hashtable.
//
// By doing this, we only create Vector for those method names
// that correspond to more than one CallGraphNode
Vector v = new Vector(2);
v.addElement(obj);
v.addElement(cgNode);
nodesByName.put(cgNode.name, v);
}
| void | createCallGraph()
// Now all the CallGraphNodes are created. We're ready to
// construct the call graph
for (Enumeration e = nodes.elements(); e.hasMoreElements() ;) {
CallGraphNode cgNode = (CallGraphNode)e.nextElement();
if (cgNode.parentIdx == null) {
// This is the root record. Do nothing
} else {
CallGraphNode parent;
parent = (CallGraphNode)nodes.get(cgNode.parentIdx);
if (parent == null) {
System.out.println("WARNING: no parent found for element " +
cgNode);
parent = root;
}
if (parent.children == null) {
parent.children = new Vector();
numParents ++;
}
parent.children.addElement(cgNode);
cgNode.parent = parent;
}
}
| CallGraphNode | createTopNode(CallGraphNode parent, int index, java.lang.String name)
CallGraphNode r = new CallGraphNode(parent);
r.parent = parent;
r.parentIdx = parent == null ? null : parent.index;
r.index = new Integer(index);
r.name = name;
nodes.put(r.index, r);
addToIndexByName(r);
return r;
| boolean | isMultifile()
return numFiles > 1;
| void | printRecord(CallGraphNode cgNode, java.lang.String prefix)
if (cgNode.parent != null) {
System.out.print(prefix);
System.out.print(cgNode.name);
System.out.print(", D=" + cgNode.depth);
System.out.print(", K=" + cgNode.count);
System.out.print(", C=" + cgNode.kidsCycles);
System.out.print(", M=" + cgNode.kidsMsec);
System.out.println();
prefix += " ";
}
if (cgNode.children != null) {
Vector v = cgNode.children;
for (int i=0; i<v.size(); i++) {
printRecord((CallGraphNode)v.elementAt(i), prefix);
}
}
| void | readInputFile(FileParserContext ctx)Read the entire content of an input file
FileReader fr = new FileReader(ctx.file);
BufferedReader reader = new BufferedReader(fr);
String line;
/* Skip the first line. It's for human consumption only */
line = reader.readLine();
//line = reader.readLine(); /* need revisit */
// Read all lines in the input file
//
while ((line = reader.readLine()) != null) {
readInputLine(line, ctx);
}
| void | readInputLine(java.lang.String line, FileParserContext ctx)
StringTokenizer st = new StringTokenizer(line);
if (st.countTokens() != 15) {
return;
}
// Read the raw content of the input line into the CallGraphNode
try {
CallGraphNode cgNode;
int index = Integer.parseInt(st.nextToken());
if (index == -1) {
// We also have a predefined root node in our source file -
// so modify the existing root node
cgNode = ctx.root;
st.nextToken(); // parent token is meaningless for the root
} else {
cgNode = new CallGraphNode(ctx.root);
cgNode.index = new Integer(ctx.indexOffset + index);
cgNode.parentIdx = new Integer(ctx.indexOffset +
Integer.parseInt(st.nextToken()));
}
cgNode.depth = Integer.parseInt(st.nextToken());
cgNode.name = st.nextToken();
cgNode.count = Integer.parseInt(st.nextToken());
cgNode.onlyCycles = Long.parseLong(st.nextToken());
cgNode.onlyMsec = Double.parseDouble(st.nextToken());
cgNode.onlyPerc = Double.parseDouble(st.nextToken());
if (index != -1) {
// kidsCylcles is calculated automatically for the root node
cgNode.kidsCycles = Long.parseLong(st.nextToken());
cgNode.kidsMsec = Double.parseDouble(st.nextToken());
cgNode.kidsPerc = Double.parseDouble(st.nextToken());
// Timeline information
cgNode.startTime = Double.parseDouble(st.nextToken());
cgNode.endTime = Double.parseDouble(st.nextToken());
if (cgNode.endTime > period) {
period = cgNode.endTime;
}
// Store new CallGraphNode into the hashtable
nodes.put(cgNode.index, cgNode);
// Add it to another index table, searchable by cgNode.name
addToIndexByName(cgNode);
}
} catch (NumberFormatException e) {
// IMPL_NOTE: warning
}
|
|