Skip to content

Commit 0113d25

Browse files
committed
Script to process method trace result file
1 parent 327cf1c commit 0113d25

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

process_trace.rb

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# Reads a call trace, formatted as
4+
#
5+
# [<>][stack_depth][thread]called_method=time_nanosecs
6+
#
7+
# and produces the total time spent in each method.
8+
# Lines that start with > denote method entry
9+
# < denote method exit
10+
# (c) 2011 - Georgios Gousios <gousiosg@gmail.com>
11+
#
12+
13+
require 'rubygems'
14+
15+
if ARGV.size <= 0 then
16+
print "usage: timings.rb timings file"
17+
end
18+
19+
results = Hash.new
20+
mstack = Array.new
21+
tstack = Array.new
22+
total_time_at_depth = Hash.new
23+
lines_read = 0
24+
d = 0
25+
26+
File.open(ARGV[0]).each do |line|
27+
type, depth, tid, method, time = line.scan(/([<>])\[(\d+)\]\[(\d+)\](.*)=(\d+)/)[0]
28+
lines_read += 1
29+
depth = depth.to_i
30+
time = time.to_i
31+
32+
case type
33+
when '<':
34+
# Can only return from inner or same depth level frame
35+
if not [d, d - 1].include? depth then
36+
print "Return from stack depth: ", d,
37+
" to depth:", depth, ", line ",
38+
lines_read, "\n"
39+
return
40+
end
41+
m = mstack.pop
42+
t = tstack.pop
43+
44+
# Sanity check
45+
if not m == method then
46+
print "Method ", method, " not found at depth ",
47+
depth, " line ", lines_read, "\n"
48+
return
49+
end
50+
51+
# Total time for a method is the time to execute it minus the time to
52+
# invoke all called methods
53+
method_time = time - t
54+
results[method] = results.fetch(method, 0) + method_time -
55+
total_time_at_depth.fetch(depth + 1, 0)
56+
57+
# Sanity check
58+
if method_time - total_time_at_depth.fetch(depth + 1, 0) < 0 then
59+
print "Time required for method #{method} (#{method_time}) less
60+
than time for required for inner frame
61+
(#{total_time_at_depth.fetch(depth + 1, 0)})! ",
62+
"Line ", lines_read, "\n"
63+
return
64+
end
65+
66+
# Total for a frame is the total time of its first level decendant
67+
# plus the time required to execute all methods at the same depth
68+
total_time_at_depth[depth] = method_time -
69+
total_time_at_depth.fetch(depth + 1, 0) +
70+
total_time_at_depth.fetch(depth, 0)
71+
# Inner stack frame time was used already at this depth,
72+
# delete to avoid reusing
73+
total_time_at_depth.delete(depth + 1)
74+
75+
# Reset total time for depth 0 after it has been used
76+
# since the statement above never runs at this depth
77+
if depth == 0:
78+
total_time_at_depth.delete(depth)
79+
end
80+
when '>':
81+
# Can only go into an inner or same depth level frame
82+
if not [d, d + 1].include? depth then
83+
print "Jump from stack depth: #{d} to depth: #{depth},
84+
line #{lines_read} \n"
85+
return
86+
end
87+
mstack.push method
88+
tstack.push time
89+
else print "Cannot parse line #{line}"
90+
end
91+
d = depth
92+
end
93+
94+
# Print results sorted
95+
results.sort{|a,b| b[1]<=>a[1]}.each {|x|
96+
print "#{x[0]} #{x[1]}\n"
97+
}

0 commit comments

Comments
 (0)