class RubyProf::GraphHtmlPrinter

  1. lib/ruby-prof/graph_html_printer.rb
Parent: RubyProf

Generates graph profile reports as html. To use the graph html printer:

result = RubyProf.profile do
  [code to profile]

printer =
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



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
def initialize(result)
  @thread_times =

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 76
def calculate_thread_times
  # Cache thread times since this is an expensive
  # operation with the required sorting
  @overall_threads_time = 0.0
  @thread_times =
  @result.threads.each do |thread_id, methods|
    roots ={|m| m.root?}
    thread_total_time = sum({|r| self.total_time(r.call_infos)})
    @overall_threads_time += thread_total_time
    @thread_times[thread_id] = thread_total_time
method_href (thread_id, method)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 117
def method_href(thread_id, method)
  h(method.full_name.gsub(%r[><#\.\?=:]/,"_") + "_" + thread_id.to_s)
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.

unique options are:

:filename    - specify a file to use that contains the ERB
               template to use, instead of the built-in self.template
:template    - specify an ERB template to use, instead of the
               built-in self.template
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 53
def print(output = STDOUT, options = {})
  @output = output

  filename = options[:filename]
  template = filename ? : (options[:template] || self.template)
  _erbout = @output
  erb =, nil, nil)
  erb.filename = filename
  @output << erb.result(binding)
self_percent (method)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 98
def self_percent(method)
  overall_time = self.thread_time(method.thread_id)
  (method.self_time/overall_time) * 100
sum (a)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 69
def sum(a)
  a.inject(0.0){|s,t| s+=t}
template ()
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 134
    def template
  <style media="all" type="text/css">
    table {
      border-collapse: collapse;
      border: 1px solid #CCC;
      font-family: Verdana, Arial, Helvetica, sans-serif;
      font-size: 9pt;
      line-height: normal;
      width: 100%;

    th {
      text-align: center;
      border-top: 1px solid #FB7A31;
      border-bottom: 1px solid #FB7A31;
      background: #FFC;
      padding: 0.3em;
      border-left: 1px solid silver;

    tr.break td {
      border: 0;
      border-top: 1px solid #FB7A31;
      padding: 0;
      margin: 0;

    tr.method td {
      font-weight: bold;

    td {
      padding: 0.3em;

    td:first-child {
      width: 190px;

    td {
      border-left: 1px solid #CCC;
      text-align: center;

    .method_name {
      text-align: left;
    <h1>Profile Report</h1>
    <!-- Threads Table -->
        <th>Thread ID</th>
        <th>Total Time</th>
      <% for thread_id in @result.threads.keys.sort %>
        <td><a href="#<%= thread_id %>"><%= thread_id %></a></td>
        <td><%= thread_time(thread_id) %></td>
      <% end %>

    <!-- Methods Tables -->
    <% for thread_id in @result.threads.keys.sort
         methods = @result.threads[thread_id]
         total_time = thread_time(thread_id) %>
      <h2><a name="<%= thread_id %>">Thread <%= thread_id %></a></h2>

          <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %></th>
          <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %></th>
          <th><%= sprintf("%#{TIME_WIDTH}s", "Total") %></th>
          <th><%= sprintf("%#{TIME_WIDTH}s", "Self") %></th>
          <th><%= sprintf("%#{TIME_WIDTH}s", "Wait") %></th>
          <th><%= sprintf("%#{TIME_WIDTH+2}s", "Child") %></th>
          <th><%= sprintf("%#{CALL_WIDTH}s", "Calls") %></th>
          <th class="method_name">Name</th>

        <% min_time = @options[:min_time] || (@options[:nonzero] ? 0.005 : nil)
           methods.sort_by(&sort_method).reverse_each do |method|
            total_percentage = (method.total_time/total_time) * 100
            next if total_percentage < min_percent
            next if min_time && method.total_time < min_time
            self_percentage = (method.self_time/total_time) * 100 %>

            <!-- Parents -->
            <% for caller in method.aggregate_parents.sort_by(&:total_time)
                 next unless caller.parent
                 next if min_time && caller.total_time < min_time  %>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
                <% called = "#{caller.called}/#{method.called}" %>
                <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
                <td class="method_name"><%= create_link(thread_id, %></td>
                <td><%= file_link(, caller.line) %></td>
            <% end %>

            <tr class="method">
              <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
              <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
              <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
              <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
              <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
              <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
              <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
              <td class="method_name"><a name="<%= method_href(thread_id, method) %>"><%= h method.full_name %></a></td>
              <td><%= file_link(method.source_file, method.line) %></td>

            <!-- Children -->
            <% for callee in method.aggregate_children.sort_by(&:total_time).reverse %>
            <%   next if min_time && callee.total_time < min_time  %>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
                <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
                <% called = "#{callee.called}/#{}" %>
                <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
                <td class="method_name"><%= create_link(thread_id, %></td>
                <td><%= file_link(method.source_file, callee.line) %></td>
            <% end %>
            <!-- Create divider row -->
            <tr class="break"><td colspan="9"></td></tr>
        <% end %>
    <% end %>
thread_time (thread_id)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 89
def thread_time(thread_id)
total_percent (thread_id, method)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 93
def total_percent(thread_id, method)
  overall_time = self.thread_time(thread_id)
  (method.total_time/overall_time) * 100
total_time (call_infos)
[show source]
# File lib/ruby-prof/graph_html_printer.rb, line 65
def total_time(call_infos)
  sum({|ci| ci.total_time})