| Class | RubyProf::GraphHtmlPrinter |
| In: |
lib/ruby-prof/graph_html_printer.rb
|
| Parent: | AbstractPrinter |
Generates graph profile reports as html. To use the grap html printer:
result = RubyProf.profile do
[code to profile]
end
printer = RubyProf::GraphHtmlPrinter.new(result)
printer.print(STDOUT, :min_percent=>0)
The constructor takes two arguments. The first is a RubyProf::Result object generated from a profiling run. The second is the minimum %total (the methods total time divided by the overall total time) that a method must take for it to be printed out in the report. Use this parameter to eliminate methods that are not important to the overall profiling results.
| PERCENTAGE_WIDTH | = | 8 |
| TIME_WIDTH | = | 10 |
| CALL_WIDTH | = | 20 |
Create a GraphPrinter. Result is a RubyProf::Result object generated from a profiling run.
# File lib/ruby-prof/graph_html_printer.rb, line 32
32: def initialize(result)
33: super(result)
34: @thread_times = Hash.new
35: calculate_thread_times
36: end
These methods should be private but then ERB doesn’t work. Turn off RDOC though
# File lib/ruby-prof/graph_html_printer.rb, line 61
61: def calculate_thread_times
62: # Cache thread times since this is an expensive
63: # operation with the required sorting
64: @result.threads.each do |thread_id, methods|
65: top = methods.sort.last
66:
67: thread_time = 0.01
68: thread_time = top.total_time if top.total_time > 0
69:
70: @thread_times[thread_id] = thread_time
71: end
72: end
Creates a link to a method. Note that we do not create links to methods which are under the min_perecent specified by the user, since they will not be printed out.
# File lib/ruby-prof/graph_html_printer.rb, line 92
92: def create_link(thread_id, method)
93: if self.total_percent(thread_id, method) < min_percent
94: # Just return name
95: h method.full_name
96: else
97: href = '#' + method_href(thread_id, method)
98: "<a href=\"#{href}\">#{h method.full_name}</a>"
99: end
100: end
# File lib/ruby-prof/graph_html_printer.rb, line 102
102: def method_href(thread_id, method)
103: h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread_id.to_s)
104: end
Print a graph html report to the provided output.
output - Any IO oject, including STDOUT or a file. The default value is STDOUT.
options - Hash of print options. See setup_options
for more information.
# File lib/ruby-prof/graph_html_printer.rb, line 46
46: def print(output = STDOUT, options = {})
47: @output = output
48: setup_options(options)
49:
50: filename = options[:filename]
51: template = filename ? File.read(filename).untaint : (options[:template] || self.template)
52: _erbout = @output
53: erb = ERB.new(template, nil, nil)
54: erb.filename = filename
55: @output << erb.result(binding)
56: end
# File lib/ruby-prof/graph_html_printer.rb, line 83
83: def self_percent(method)
84: overall_time = self.thread_time(method.thread_id)
85: (method.self_time/overall_time) * 100
86: end
# File lib/ruby-prof/graph_html_printer.rb, line 106
106: def template
107: '
108: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
109: <html>
110: <head>
111: <style media="all" type="text/css">
112: table {
113: border-collapse: collapse;
114: border: 1px solid #CCC;
115: font-family: Verdana, Arial, Helvetica, sans-serif;
116: font-size: 9pt;
117: line-height: normal;
118: }
119:
120: th {
121: text-align: center;
122: border-top: 1px solid #FB7A31;
123: border-bottom: 1px solid #FB7A31;
124: background: #FFC;
125: padding: 0.3em;
126: border-left: 1px solid silver;
127: }
128:
129: tr.break td {
130: border: 0;
131: border-top: 1px solid #FB7A31;
132: padding: 0;
133: margin: 0;
134: }
135:
136: tr.method td {
137: font-weight: bold;
138: }
139:
140: td {
141: padding: 0.3em;
142: }
143:
144: td:first-child {
145: width: 190px;
146: }
147:
148: td {
149: border-left: 1px solid #CCC;
150: text-align: center;
151: }
152:
153: .method_name {
154: text-align: left;
155: max-width: 25em;
156: }
157: </style>
158: </head>
159: <body>
160: <h1>Profile Report</h1>
161: <!-- Threads Table -->
162: <table>
163: <tr>
164: <th>Thread ID</th>
165: <th>Total Time</th>
166: </tr>
167: <% for thread_id, methods in @result.threads %>
168: <tr>
169: <td><a href="#<%= thread_id %>"><%= thread_id %></a></td>
170: <td><%= thread_time(thread_id) %></td>
171: </tr>
172: <% end %>
173: </table>
174:
175: <!-- Methods Tables -->
176: <% for thread_id, methods in @result.threads
177: total_time = thread_time(thread_id) %>
178: <h2><a name="<%= thread_id %>">Thread <%= thread_id %></a></h2>
179:
180: <table>
181: <tr>
182: <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %></th>
183: <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %></th>
184: <th><%= sprintf("%#{TIME_WIDTH}s", "Total") %></th>
185: <th><%= sprintf("%#{TIME_WIDTH}s", "Self") %></th>
186: <th><%= sprintf("%#{TIME_WIDTH}s", "Wait") %></th>
187: <th><%= sprintf("%#{TIME_WIDTH+2}s", "Child") %></th>
188: <th><%= sprintf("%#{CALL_WIDTH}s", "Calls") %></th>
189: <th class="method_name">Name</th>
190: <th>Line</th>
191: </tr>
192:
193: <% min_time = @options[:min_time] || (@options[:nonzero] ? 0.005 : nil)
194: methods.sort.reverse_each do |method|
195: total_percentage = (method.total_time/total_time) * 100
196: next if total_percentage < min_percent
197: next if min_time && method.total_time < min_time
198: self_percentage = (method.self_time/total_time) * 100 %>
199:
200: <!-- Parents -->
201: <% for caller in method.parents %>
202: <% next if min_time && caller.total_time < min_time %>
203: <tr>
204: <td> </td>
205: <td> </td>
206: <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
207: <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
208: <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
209: <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
210: <% called = "#{caller.called}/#{method.called}" %>
211: <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
212: <td class="method_name"><%= create_link(thread_id, caller.target) %></td>
213: <td><a href="file://<%=h srcfile=File.expand_path(caller.target.source_file) %>#line=<%= linenum=caller.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= caller.line %></a></td>
214: </tr>
215: <% end %>
216:
217: <tr class="method">
218: <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
219: <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
220: <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
221: <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
222: <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
223: <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
224: <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
225: <td class="method_name"><a name="<%= method_href(thread_id, method) %>"><%= h method.full_name %></a></td>
226: <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=method.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= method.line %></a></td>
227: </tr>
228:
229: <!-- Children -->
230: <% for callee in method.children %>
231: <% next if min_time && callee.total_time < min_time %>
232: <tr>
233: <td> </td>
234: <td> </td>
235: <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
236: <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
237: <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
238: <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
239: <% called = "#{callee.called}/#{callee.target.called}" %>
240: <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
241: <td class="method_name"><%= create_link(thread_id, callee.target) %></td>
242: <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=callee.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= callee.line %></a></td>
243: </tr>
244: <% end %>
245: <!-- Create divider row -->
246: <tr class="break"><td colspan="9"></td></tr>
247: <% end %>
248: </table>
249: <% end %>
250: </body>
251: </html>'
252: end
# File lib/ruby-prof/graph_html_printer.rb, line 74
74: def thread_time(thread_id)
75: @thread_times[thread_id]
76: end