Moved "Shell" code into a "Glob" type/namespace, and removed FormatSpecification...
[cslatevm.git] / src / profiler / profpp.py
blob22188e341973822100296ec1a120fed56e2f6365
1 #!/usr/bin/env python
3 import struct
4 import sys
6 wordSize = 8
7 structFormat = 'qqq'
9 def incrementEntry(dict, entry, amt):
10 if entry == None:
11 return
12 if entry not in dict:
13 dict[entry] = amt
14 else:
15 dict[entry] += amt
18 def readCalls(callsFilename):
19 fd = open(callsFilename, 'rb')
20 callCount = {}
21 selfTime = {}
22 cumTime = {}
23 childTime = {}
24 callStack = []
25 callStackTime = []
26 childCallCount = {}
27 lastTime = 0
28 lastDepth = None
29 inFunction = None
30 progressCounter = 0
31 while True:
32 entry = fd.read(3 * wordSize)
33 if (entry == ''):
34 break
35 time, depth, method = struct.unpack(structFormat, entry)
36 timeDiff = time - lastTime
37 progressCounter += timeDiff
38 if progressCounter > 1000000:
39 sys.stderr.write("Processed a second of time... at " + str(time/1000000) + " seconds\n")
40 progressCounter -= 1000000
41 # sys.stderr.write(str(len(selfTime)))
42 # sys.stderr.write("\n")
43 # sys.stderr.write(str(len(cumTime)))
44 # sys.stderr.write("\n")
45 # sys.stderr.write(str(len(childTime)))
46 # sys.stderr.write("\n")
47 # sys.stderr.write(str(len(childCallCount)))
48 # sys.stderr.write("\n")
49 # sys.stderr.write(str(len(callCount)))
50 # sys.stderr.write("\n")
51 # sys.stderr.write(str(len(callStack)))
52 # sys.stderr.write("\n")
54 #call count
55 incrementEntry(callCount, method, 1)
56 #self time
57 incrementEntry(selfTime, method, timeDiff)
59 #cumulative time
60 if lastDepth == None or depth > lastDepth:
61 #child call Count
62 if len(callStack) >= 1:
63 parent = callStack[-1]
64 parentTime = callStackTime[-1]
65 if parent not in childCallCount:
66 childCallCount[parent] = {}
67 incrementEntry(childCallCount[parent], method, 1)
68 callStack.append(method)
69 callStackTime.append(time)
70 else:
71 if len(callStack) > 1:
72 child = callStack.pop()
73 startTime = callStackTime.pop()
74 if child not in callStack: # don't double count?
75 incrementEntry(cumTime, child, time - startTime)
76 if len(callStack) > 1:
77 parent = callStack[-1]
78 if parent not in childTime:
79 childTime[parent] = {}
80 incrementEntry(childTime[parent], child, time - startTime)
85 lastTime = time
86 lastDepth = depth
87 #print("time: " + str(time) + " depth: " + str(depth) + " method: " + str(method))
88 fd.close()
89 return selfTime, cumTime, childTime, childCallCount, callCount, lastTime
92 def readKeys(keysFilename):
93 fd = open(keysFilename, 'rb')
94 dict = {}
95 for line in fd:
96 key, fn = line.split('->', 1)
97 key = key.strip()
98 fn = fn.strip()
99 dict[int(key)] = fn
100 fd.close()
101 return dict
103 def methodColor(percent):
104 return "#000000"
106 def main(args):
107 if len(args) != 3:
108 print("USAGE: " + sys.argv[0] + " <profcalls.out> <profkeys.out> <max-count>")
109 return
110 callsFilename = args[0]
111 keysFilename = args[1]
112 maxCount = int(args[2])
113 maxCountDict = {}
114 keys = readKeys(keysFilename)
115 # print(str(keys))
116 selfTime, cumTime, childTime, childCallCount, callCount, lastTime = readCalls(callsFilename)
117 # print(str(selfTime))
118 # print(str(cumTime))
119 # print(str(childTime))
120 # print(str(childCallCount))
121 # print(str(callCount))
122 # print(str(sorted([(val, key) for key, val in cumTime.items()], key = lambda (x,y): x, reverse = True)))
123 print("digraph {\ngraph [ranksep=0.25, fontname=Arial, nodesep=0.125];\n"
124 "node [fontname=Arial, style=\"filled,rounded\", height=0, width=0, shape=box, fontcolor=white];\n"
125 "edge [fontname=Arial];\n")
127 for parentMethod, childMethods in childCallCount.items():
128 for method, count in childMethods.items():
129 if method not in keys:
130 keys[method] = '???'
132 functionOrder = sorted([(val, key) for key, val in cumTime.items()], key = lambda (x,y): x, reverse = True)
133 #print "index % time self children called name"
134 index = 0
135 for time, method in functionOrder:
136 maxCountDict[method] = True
137 if (index > maxCount):
138 break
139 index += 1
141 for time, method in functionOrder:
142 selfPercent = round(selfTime[method]*100.0/lastTime, 2)
143 cumPercent = round(cumTime[method]*100.0/lastTime, 2)
144 if method not in maxCountDict:
145 continue
146 print(str(method) + " [color=\"" + methodColor(cumPercent)+ "\", fontcolor=\"#ffffff\", fontsize=\"10.00\", "
147 "label=\"" + str(keys[method]) + "\\n" + str(cumPercent) + "%\\n(" + str(selfPercent) + "%)\\n" +
148 str(callCount[method]) + "\"]")
149 if method in childTime:
150 childTimes = childTime[method]
151 fullChildTime = 0
152 for childMethod, childFullTime in childTimes.items():
153 fullChildTime += childFullTime
155 for childMethod, childFullTime in childTimes.items():
156 if childMethod not in maxCountDict:
157 continue
158 childPercentTime = round(childFullTime * 100.0 / fullChildTime, 2)
159 if childMethod not in childCallCount[method]:
160 cCount = '0'
161 else:
162 cCount = str(childCallCount[method][childMethod])
163 print(str(method) + " -> " + str(childMethod) +
164 " [color=\"" + methodColor(childPercentTime)+ "\", fontcolor=\"#000000\", fontsize=\"10.00\", "
165 "penwidth=\"1.0\", label=\"" + str(childPercentTime) + "%\\n" + cCount + "\"]")
169 print "\n}\n"
170 #for method in [[key, val] for key, val in selfTime.items()].sort(key = lambda obj: obj[1]):
171 #print(str(keys[method]))
175 if __name__ == "__main__":
176 main(sys.argv[1:])