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
public class
public instance
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.
# 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
# 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: 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> </td> 206: <td> </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> </td> 235: <td> </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
# File lib/ruby-prof/graph_html_printer.rb, line 74 74: def thread_time(thread_id) 75: @thread_times[thread_id] 76: end
# 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