require "erb" module RubyProf # Generates graph[link:files/examples/graph_html.html] 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. class GraphHtmlPrinter PERCENTAGE_WIDTH = 8 TIME_WIDTH = 10 CALL_WIDTH = 20 # Create a GraphPrinter. Result is a RubyProf::Result # object generated from a profiling run. def initialize(result) @result = result end # Print a graph html report to the provided output. # # output - Any IO oject, including STDOUT or a file. # The default value is STDOUT. # # min_percent - 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. Default value is 0. def print(output = STDOUT, min_percent = 0) @output = output @min_percent = min_percent _erbout = @output erb = ERB.new(template, nil, nil) @output << erb.result(binding) end # These methods should be private but then ERB doesn't # work. Turn off RDOC though #-- def total_time(thread_id) toplevel = @result.toplevel(thread_id) total_time = toplevel.total_time total_time = 0.01 if total_time == 0 return total_time end def total_percent(method) overall_time = self.total_time(method.thread_id) (method.total_time/overall_time) * 100 end def self_percent(method) overall_time = self.total_time(method.thread_id) (method.self_time/overall_time) * 100 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. def create_link(thread_id, name) # Get method method = @result.threads[thread_id][name] if self.total_percent(method) < @min_percent # Just return name name else # Create link "#{name}" end end def link_name(thread_id, name)\ name.gsub(/[><#\.\?=:]/,"_") + "_" + thread_id.to_s end def template '

Profile Report

<% for thread_id, methods in @result.threads %> <% end %>
Thread ID Total Time
<%= thread_id %> <%= @result.toplevel(thread_id).total_time %>
<% for thread_id, methods in @result.threads %>

Thread <%= thread_id %>

<% methods.sort.reverse.each do |pair| %> <% name = pair[0] %> <% method = pair[1] %> <% method_total_percent = self.total_percent(method) %> <% next if method_total_percent < @min_percent %> <% method_self_percent = self.self_percent(method) %> <% for name, call_info in method.parents %> <% called = "#{call_info.called}/#{method.called}" %> <% end %> <% for name, call_info in method.children %> <% methods = @result.threads[thread_id] %> <% child = methods[name] %> <% called = "#{call_info.called}/#{child.called}" %> <% end %> <% end %>
<%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %> <%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %> <%= sprintf("%#{TIME_WIDTH}s", "Total") %> <%= sprintf("%#{TIME_WIDTH}s", "Self") %> <%= sprintf("%#{TIME_WIDTH+2}s", "Children") %> <%= sprintf("%#{CALL_WIDTH}s", "Calls") %> Name
    <%= sprintf("%#{TIME_WIDTH}.2f", call_info.total_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", call_info.self_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", call_info.children_time) %><%= sprintf("%#{CALL_WIDTH}s", called) %> <%= create_link(thread_id, name) %>
<%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", method_total_percent) %> <%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", method_self_percent) %> <%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %> <%= sprintf("%#{CALL_WIDTH}i", method.called) %> <%= method.name %>
    <%= sprintf("%#{TIME_WIDTH}.2f", call_info.total_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", call_info.self_time) %> <%= sprintf("%#{TIME_WIDTH}.2f", call_info.children_time) %><%= sprintf("%#{CALL_WIDTH}s", called) %> <%= create_link(thread_id, name) %>
<% end %> ' end end end