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, 5)
  printer.print(STDOUT, 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 58
58:     def calculate_thread_times
59:       # Cache thread times since this is an expensive
60:       # operation with the required sorting      
61:       @result.threads.each do |thread_id, methods|
62:         top = methods.sort.last
63:         
64:         thread_time = 0.01
65:         thread_time = top.total_time if top.total_time > 0
66: 
67:         @thread_times[thread_id] = thread_time 
68:       end
69:     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 89
89:     def create_link(thread_id, method)
90:       if self.total_percent(thread_id, method) < min_percent
91:         # Just return name
92:         h method.full_name
93:       else
94:         href = '#' + method_href(thread_id, method)
95:         "<a href=\"#{href}\">#{h method.full_name}</a>" 
96:       end
97:     end

[Source]

     # File lib/ruby-prof/graph_html_printer.rb, line 99
 99:     def method_href(thread_id, method)
100:       h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread_id.to_s)
101:     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:       _erbout = @output
51:       erb = ERB.new(template, nil, nil)
52:       @output << erb.result(binding)
53:     end

[Source]

    # File lib/ruby-prof/graph_html_printer.rb, line 80
80:     def self_percent(method)
81:       overall_time = self.thread_time(method.thread_id)
82:       (method.self_time/overall_time) * 100
83:     end

[Source]

     # File lib/ruby-prof/graph_html_printer.rb, line 103
103:     def template
104: '
105: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
106: <html>
107: <head>
108:   <style media="all" type="text/css">
109:     table {
110:       border-collapse: collapse;
111:       border: 1px solid #CCC;
112:       font-family: Verdana, Arial, Helvetica, sans-serif;
113:       font-size: 9pt;
114:       line-height: normal;
115:     }
116: 
117:     th {
118:       text-align: center;
119:       border-top: 1px solid #FB7A31;
120:       border-bottom: 1px solid #FB7A31;
121:       background: #FFC;
122:       padding: 0.3em;
123:       border-left: 1px solid silver;
124:     }
125: 
126:     tr.break td {
127:       border: 0;
128:       border-top: 1px solid #FB7A31;
129:       padding: 0;
130:       margin: 0;
131:     }
132: 
133:     tr.method td {
134:       font-weight: bold;
135:     }
136: 
137:     td {
138:       padding: 0.3em;
139:     }
140: 
141:     td:first-child {
142:       width: 190px;
143:       }
144: 
145:     td {
146:       border-left: 1px solid #CCC;
147:       text-align: center;
148:     } 
149:   </style>
150:   </head>
151:   <body>
152:     <h1>Profile Report</h1>
153:     <!-- Threads Table -->
154:     <table>
155:       <tr>
156:         <th>Thread ID</th>
157:         <th>Total Time</th>
158:       </tr>
159:       <% for thread_id, methods in @result.threads %>
160:       <tr>
161:         <td><a href="#<%= thread_id %>"><%= thread_id %></a></td>
162:         <td><%= thread_time(thread_id) %></td>
163:       </tr>
164:       <% end %>
165:     </table>
166: 
167:     <!-- Methods Tables -->
168:     <% for thread_id, methods in @result.threads
169:          total_time = thread_time(thread_id) %>
170:       <h2><a name="<%= thread_id %>">Thread <%= thread_id %></a></h2>
171: 
172:       <table>
173:         <tr>
174:           <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %></th>
175:           <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %></th>
176:           <th><%= sprintf("%#{TIME_WIDTH}s", "Total") %></th>
177:           <th><%= sprintf("%#{TIME_WIDTH}s", "Self") %></th>
178:           <th><%= sprintf("%#{TIME_WIDTH}s", "Wait") %></th>
179:           <th><%= sprintf("%#{TIME_WIDTH+2}s", "Child") %></th>
180:           <th><%= sprintf("%#{CALL_WIDTH}s", "Calls") %></th>
181:           <th>Name</th>
182:           <th>Line</th>
183:         </tr>
184: 
185:         <% methods.sort.reverse_each do |method|
186:             total_percentage = (method.total_time/total_time) * 100
187:             next if total_percentage < min_percent
188:             self_percentage = (method.self_time/total_time) * 100 %>
189:           
190:             <!-- Parents -->
191:             <% for caller in method.parents %> 
192:               <tr>
193:                 <td>&nbsp;</td>
194:                 <td>&nbsp;</td>
195:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
196:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
197:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
198:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
199:                 <% called = "#{caller.called}/#{method.called}" %>
200:                 <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
201:                 <td><%= create_link(thread_id, caller.target) %></td>
202:                 <td><a href="file://<%= File.expand_path(caller.target.source_file) %>#line=<%= caller.line %>"><%= caller.line %></a></td>
203:               </tr>
204:             <% end %>
205: 
206:             <tr class="method">
207:               <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
208:               <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
209:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
210:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
211:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
212:               <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
213:               <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
214:               <td><a name="<%= method_href(thread_id, method) %>"><%= h method.full_name %></a></td>
215:               <td><a href="file://<%= File.expand_path(method.source_file) %>#line=<%= method.line %>"><%= method.line %></a></td>
216:             </tr>
217: 
218:             <!-- Children -->
219:             <% for callee in method.children %> 
220:               <tr>
221:                 <td>&nbsp;</td>
222:                 <td>&nbsp;</td>
223:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
224:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
225:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
226:                 <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
227:                 <% called = "#{callee.called}/#{callee.target.called}" %>
228:                 <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
229:                 <td><%= create_link(thread_id, callee.target) %></td>
230:                 <td><a href="file://<%= File.expand_path(method.source_file) %>#line=<%= callee.line %>"><%= callee.line %></a></td>
231:               </tr>
232:             <% end %>
233:             <!-- Create divider row -->
234:             <tr class="break"><td colspan="8"></td></tr>
235:         <% end %>
236:       </table>
237:     <% end %>
238:   </body>
239: </html>'
240:     end

[Source]

    # File lib/ruby-prof/graph_html_printer.rb, line 71
71:     def thread_time(thread_id)
72:       @thread_times[thread_id]
73:     end

[Source]

    # File lib/ruby-prof/graph_html_printer.rb, line 75
75:     def total_percent(thread_id, method)
76:       overall_time = self.thread_time(thread_id)
77:       (method.total_time/overall_time) * 100
78:     end

[Validate]