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.

Methods

Included Modules

ERB::Util

Constants

PERCENTAGE_WIDTH = 8
TIME_WIDTH = 10
CALL_WIDTH = 20

Public Class methods

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

[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

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

[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

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.

[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

[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 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.

[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

[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

[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:     }
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>&nbsp;</td>
205:                 <td>&nbsp;</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>&nbsp;</td>
234:                 <td>&nbsp;</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

[Source]

    # File lib/ruby-prof/graph_html_printer.rb, line 74
74:     def thread_time(thread_id)
75:       @thread_times[thread_id]
76:     end

[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

[Validate]