Class RubyProf::GraphHtmlPrinter

  1. lib/ruby-prof/graph_html_printer.rb

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.

Included modules

  1. ERB::Util

Constants

PERCENTAGE_WIDTH = 8
TIME_WIDTH = 10
CALL_WIDTH = 20

Public class methods

new (result)

Create a GraphPrinter. Result is a RubyProf::Result object generated from a profiling run.

[show source]
    # 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

Public instance methods

calculate_thread_times ()

These methods should be private but then ERB doesn’t work. Turn off RDOC though

[show source]
    # 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
create_link (thread_id, method)

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.

[show source]
     # 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
method_href (thread_id, method)
[show source]
     # 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 (output = STDOUT, options = {})

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.
[show source]
    # 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
self_percent (method)
[show source]
    # 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
template ()
[show source]
     # 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:       width: 100%;
119:     }
120: 
121:     th {
122:       text-align: center;
123:       border-top: 1px solid #FB7A31;
124:       border-bottom: 1px solid #FB7A31;
125:       background: #FFC;
126:       padding: 0.3em;
127:       border-left: 1px solid silver;
128:     }
129: 
130:     tr.break td {
131:       border: 0;
132:       border-top: 1px solid #FB7A31;
133:       padding: 0;
134:       margin: 0;
135:     }
136: 
137:     tr.method td {
138:       font-weight: bold;
139:     }
140: 
141:     td {
142:       padding: 0.3em;
143:     }
144: 
145:     td:first-child {
146:       width: 190px;
147:       }
148: 
149:     td {
150:       border-left: 1px solid #CCC;
151:       text-align: center;
152:     } 
153: 
154:     .method_name {
155:       text-align: left;
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.aggregate_parents
202:                  next unless caller.parent
203:                  next if min_time && caller.total_time < min_time  %>
204:               <tr>
205:                 <td>&nbsp;</td>
206:                 <td>&nbsp;</td>
207:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
208:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
209:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
210:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
211:                 <% called = "#{caller.called}/#{method.called}" %>
212:                 <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
213:                 <td class="method_name"><%= create_link(thread_id, caller.parent.target) %></td>
214:                 <td><a href="file://<%=h srcfile=File.expand_path(caller.parent.target.source_file) %>#line=<%= linenum=caller.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= caller.line %></a></td>
215:               </tr>
216:             <% end %>
217: 
218:             <tr class="method">
219:               <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
220:               <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
221:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
222:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
223:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
224:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
225:               <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
226:               <td class="method_name"><a name="<%= method_href(thread_id, method) %>"><%= h method.full_name %></a></td>
227:               <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=method.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= method.line %></a></td>
228:             </tr>
229: 
230:             <!-- Children -->
231:             <% for callee in method.aggregate_children %>
232:             <%   next if min_time && callee.total_time < min_time  %>
233:               <tr>
234:                 <td>&nbsp;</td>
235:                 <td>&nbsp;</td>
236:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
237:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
238:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
239:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
240:                 <% called = "#{callee.called}/#{callee.target.called}" %>
241:                 <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
242:                 <td class="method_name"><%= create_link(thread_id, callee.target) %></td>
243:                 <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=callee.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= callee.line %></a></td>
244:               </tr>
245:             <% end %>
246:             <!-- Create divider row -->
247:             <tr class="break"><td colspan="9"></td></tr>
248:         <% end %>
249:       </table>
250:     <% end %>
251:   </body>
252: </html>'
253:     end
thread_time (thread_id)
[show source]
    # File lib/ruby-prof/graph_html_printer.rb, line 74
74:     def thread_time(thread_id)
75:       @thread_times[thread_id]
76:     end
total_percent (thread_id, method)
[show source]
    # File lib/ruby-prof/graph_html_printer.rb, line 78
78:     def total_percent(thread_id, method)
79:       overall_time = self.thread_time(thread_id)
80:       (method.total_time/overall_time) * 100
81:     end