ruby-prof-danielhoey 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +221 -0
 - data/LICENSE +23 -0
 - data/README +432 -0
 - data/Rakefile +158 -0
 - data/bin/ruby-prof +224 -0
 - data/examples/flat.txt +55 -0
 - data/examples/graph.html +823 -0
 - data/examples/graph.txt +170 -0
 - data/ext/ruby_prof/call_tree.c +392 -0
 - data/ext/ruby_prof/call_tree.h +32 -0
 - data/ext/ruby_prof/extconf.rb +40 -0
 - data/ext/ruby_prof/list.c +66 -0
 - data/ext/ruby_prof/list.h +10 -0
 - data/ext/ruby_prof/measure_allocations.h +58 -0
 - data/ext/ruby_prof/measure_cpu_time.h +152 -0
 - data/ext/ruby_prof/measure_gc_runs.h +76 -0
 - data/ext/ruby_prof/measure_gc_time.h +57 -0
 - data/ext/ruby_prof/measure_memory.h +101 -0
 - data/ext/ruby_prof/measure_process_time.h +52 -0
 - data/ext/ruby_prof/measure_wall_time.h +53 -0
 - data/ext/ruby_prof/measurement.h +13 -0
 - data/ext/ruby_prof/mingw/Rakefile +23 -0
 - data/ext/ruby_prof/mingw/build.rake +38 -0
 - data/ext/ruby_prof/ruby_prof.c +1943 -0
 - data/ext/ruby_prof/ruby_prof.h +183 -0
 - data/ext/ruby_prof/version.h +4 -0
 - data/lib/ruby-prof.rb +59 -0
 - data/lib/ruby-prof/abstract_printer.rb +41 -0
 - data/lib/ruby-prof/aggregate_call_info.rb +62 -0
 - data/lib/ruby-prof/call_info.rb +47 -0
 - data/lib/ruby-prof/call_tree/abstract_printer.rb +24 -0
 - data/lib/ruby-prof/call_tree/html_printer.rb +89 -0
 - data/lib/ruby-prof/call_tree/html_printer_output.html.erb +99 -0
 - data/lib/ruby-prof/call_tree/text_printer.rb +28 -0
 - data/lib/ruby-prof/call_tree_printer.rb +84 -0
 - data/lib/ruby-prof/flat_printer.rb +78 -0
 - data/lib/ruby-prof/flat_printer_with_line_numbers.rb +72 -0
 - data/lib/ruby-prof/graph_html_printer.rb +256 -0
 - data/lib/ruby-prof/graph_printer.rb +157 -0
 - data/lib/ruby-prof/method_info.rb +111 -0
 - data/lib/ruby-prof/symbol_to_proc.rb +8 -0
 - data/lib/ruby-prof/task.rb +146 -0
 - data/lib/ruby-prof/test.rb +148 -0
 - data/lib/unprof.rb +8 -0
 - data/rails/environment/profile.rb +24 -0
 - data/rails/example/example_test.rb +9 -0
 - data/rails/profile_test_helper.rb +21 -0
 - data/test/aggregate_test.rb +121 -0
 - data/test/basic_test.rb +290 -0
 - data/test/current_failures_windows +8 -0
 - data/test/do_nothing.rb +0 -0
 - data/test/duplicate_names_test.rb +32 -0
 - data/test/enumerable_test.rb +16 -0
 - data/test/exceptions_test.rb +15 -0
 - data/test/exclude_threads_test.rb +54 -0
 - data/test/exec_test.rb +14 -0
 - data/test/line_number_test.rb +73 -0
 - data/test/measurement_test.rb +121 -0
 - data/test/module_test.rb +54 -0
 - data/test/no_method_class_test.rb +14 -0
 - data/test/prime.rb +58 -0
 - data/test/prime_test.rb +13 -0
 - data/test/printers_test.rb +130 -0
 - data/test/recursive_test.rb +275 -0
 - data/test/ruby-prof-bin +20 -0
 - data/test/singleton_test.rb +37 -0
 - data/test/stack_test.rb +138 -0
 - data/test/start_stop_test.rb +95 -0
 - data/test/test_suite.rb +23 -0
 - data/test/thread_test.rb +173 -0
 - data/test/unique_call_path_test.rb +225 -0
 - metadata +163 -0
 
| 
         @@ -0,0 +1,157 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ruby-prof/abstract_printer'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RubyProf
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Generates graph[link:files/examples/graph_txt.html] profile reports as text. 
         
     | 
| 
      
 5 
     | 
    
         
            +
              # To use the graph printer:
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              #   result = RubyProf.profile do
         
     | 
| 
      
 8 
     | 
    
         
            +
              #     [code to profile]
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              #   printer = RubyProf::GraphPrinter.new(result, 5)
         
     | 
| 
      
 12 
     | 
    
         
            +
              #   printer.print(STDOUT, 0)
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              # The constructor takes two arguments. See the README
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              class GraphPrinter < AbstractPrinter
         
     | 
| 
      
 17 
     | 
    
         
            +
                PERCENTAGE_WIDTH = 8
         
     | 
| 
      
 18 
     | 
    
         
            +
                TIME_WIDTH = 10
         
     | 
| 
      
 19 
     | 
    
         
            +
                CALL_WIDTH = 17
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
                # Create a GraphPrinter.  Result is a RubyProf::Result  
         
     | 
| 
      
 22 
     | 
    
         
            +
                # object generated from a profiling run.
         
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize(result)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  super(result)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @thread_times = Hash.new
         
     | 
| 
      
 26 
     | 
    
         
            +
                  calculate_thread_times
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def calculate_thread_times
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # Cache thread times since this is an expensive
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # operation with the required sorting      
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @result.threads.each do |thread_id, methods|
         
     | 
| 
      
 33 
     | 
    
         
            +
                    top = methods.max
         
     | 
| 
      
 34 
     | 
    
         
            +
                    
         
     | 
| 
      
 35 
     | 
    
         
            +
                    thread_time = [top.total_time, 0.01].max
         
     | 
| 
      
 36 
     | 
    
         
            +
                    
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @thread_times[thread_id] = thread_time 
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                # Print a graph report to the provided output.
         
     | 
| 
      
 42 
     | 
    
         
            +
                # 
         
     | 
| 
      
 43 
     | 
    
         
            +
                # output - Any IO oject, including STDOUT or a file. 
         
     | 
| 
      
 44 
     | 
    
         
            +
                # The default value is STDOUT.
         
     | 
| 
      
 45 
     | 
    
         
            +
                # 
         
     | 
| 
      
 46 
     | 
    
         
            +
                # options - Hash of print options.  See #setup_options 
         
     | 
| 
      
 47 
     | 
    
         
            +
                #           for more information.
         
     | 
| 
      
 48 
     | 
    
         
            +
                #
         
     | 
| 
      
 49 
     | 
    
         
            +
                def print(output = STDOUT, options = {})
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @output = output
         
     | 
| 
      
 51 
     | 
    
         
            +
                  setup_options(options)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  print_threads
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                private 
         
     | 
| 
      
 56 
     | 
    
         
            +
                def print_threads
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # sort assumes that spawned threads have higher object_ids
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @result.threads.sort.each do |thread_id, methods|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    print_methods(thread_id, methods)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @output << "\n" * 2
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
                
         
     | 
| 
      
 64 
     | 
    
         
            +
                def print_methods(thread_id, methods)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # Sort methods from longest to shortest total time
         
     | 
| 
      
 66 
     | 
    
         
            +
                  methods = methods.sort
         
     | 
| 
      
 67 
     | 
    
         
            +
                  
         
     | 
| 
      
 68 
     | 
    
         
            +
                  toplevel = methods.last
         
     | 
| 
      
 69 
     | 
    
         
            +
                  total_time = toplevel.total_time
         
     | 
| 
      
 70 
     | 
    
         
            +
                  if total_time == 0
         
     | 
| 
      
 71 
     | 
    
         
            +
                    total_time = 0.01
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  
         
     | 
| 
      
 74 
     | 
    
         
            +
                  print_heading(thread_id)
         
     | 
| 
      
 75 
     | 
    
         
            +
                
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # Print each method in total time order
         
     | 
| 
      
 77 
     | 
    
         
            +
                  methods.reverse_each do |method|
         
     | 
| 
      
 78 
     | 
    
         
            +
                    total_percentage = (method.total_time/total_time) * 100
         
     | 
| 
      
 79 
     | 
    
         
            +
                    self_percentage = (method.self_time/total_time) * 100
         
     | 
| 
      
 80 
     | 
    
         
            +
                    
         
     | 
| 
      
 81 
     | 
    
         
            +
                    next if total_percentage < min_percent
         
     | 
| 
      
 82 
     | 
    
         
            +
                    
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @output << "-" * 80 << "\n"
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                    print_parents(thread_id, method)
         
     | 
| 
      
 86 
     | 
    
         
            +
                
         
     | 
| 
      
 87 
     | 
    
         
            +
                    # 1 is for % sign
         
     | 
| 
      
 88 
     | 
    
         
            +
                    @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage)
         
     | 
| 
      
 89 
     | 
    
         
            +
                    @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", method.total_time)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", method.self_time)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", method.wait_time)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", method.children_time)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    @output << sprintf("%#{CALL_WIDTH}i", method.called)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    @output << sprintf("     %s", method_name(method))
         
     | 
| 
      
 96 
     | 
    
         
            +
                    if print_file
         
     | 
| 
      
 97 
     | 
    
         
            +
                      @output << sprintf("  %s:%s", method.source_file, method.line)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end          
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @output << "\n"
         
     | 
| 
      
 100 
     | 
    
         
            +
                
         
     | 
| 
      
 101 
     | 
    
         
            +
                    print_children(method)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
              
         
     | 
| 
      
 105 
     | 
    
         
            +
                def print_heading(thread_id)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  @output << "Thread ID: #{thread_id}\n"
         
     | 
| 
      
 107 
     | 
    
         
            +
                  @output << "Total Time: #{@thread_times[thread_id]}\n"
         
     | 
| 
      
 108 
     | 
    
         
            +
                  @output << "\n"
         
     | 
| 
      
 109 
     | 
    
         
            +
                  
         
     | 
| 
      
 110 
     | 
    
         
            +
                  # 1 is for % sign
         
     | 
| 
      
 111 
     | 
    
         
            +
                  @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
         
     | 
| 
      
 112 
     | 
    
         
            +
                  @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @output << sprintf("%#{TIME_WIDTH}s", "total")
         
     | 
| 
      
 114 
     | 
    
         
            +
                  @output << sprintf("%#{TIME_WIDTH}s", "self")
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @output << sprintf("%#{TIME_WIDTH}s", "wait")
         
     | 
| 
      
 116 
     | 
    
         
            +
                  @output << sprintf("%#{TIME_WIDTH}s", "child")
         
     | 
| 
      
 117 
     | 
    
         
            +
                  @output << sprintf("%#{CALL_WIDTH}s", "calls")
         
     | 
| 
      
 118 
     | 
    
         
            +
                  @output << "   Name"
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @output << "\n"
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
                
         
     | 
| 
      
 122 
     | 
    
         
            +
                def print_parents(thread_id, method)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  method.aggregate_parents.sort_by(&:total_time).each do |caller|
         
     | 
| 
      
 124 
     | 
    
         
            +
                    next unless caller.parent
         
     | 
| 
      
 125 
     | 
    
         
            +
                    @output << " " * 2 * PERCENTAGE_WIDTH
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", caller.total_time)
         
     | 
| 
      
 127 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", caller.self_time)
         
     | 
| 
      
 128 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", caller.wait_time)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", caller.children_time)
         
     | 
| 
      
 130 
     | 
    
         
            +
                
         
     | 
| 
      
 131 
     | 
    
         
            +
                    call_called = "#{caller.called}/#{method.called}"
         
     | 
| 
      
 132 
     | 
    
         
            +
                    @output << sprintf("%#{CALL_WIDTH}s", call_called)
         
     | 
| 
      
 133 
     | 
    
         
            +
                    @output << sprintf("     %s", caller.parent.target.full_name)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    @output << "\n"
         
     | 
| 
      
 135 
     | 
    
         
            +
                  end
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
              
         
     | 
| 
      
 138 
     | 
    
         
            +
                def print_children(method)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
         
     | 
| 
      
 140 
     | 
    
         
            +
                    # Get children method
         
     | 
| 
      
 141 
     | 
    
         
            +
                    
         
     | 
| 
      
 142 
     | 
    
         
            +
                    @output << " " * 2 * PERCENTAGE_WIDTH
         
     | 
| 
      
 143 
     | 
    
         
            +
                    
         
     | 
| 
      
 144 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", child.total_time)
         
     | 
| 
      
 145 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", child.self_time)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", child.wait_time)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    @output << sprintf("%#{TIME_WIDTH}.2f", child.children_time)
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                    call_called = "#{child.called}/#{child.target.called}"
         
     | 
| 
      
 150 
     | 
    
         
            +
                    @output << sprintf("%#{CALL_WIDTH}s", call_called)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    @output << sprintf("     %s", child.target.full_name)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    @output << "\n"
         
     | 
| 
      
 153 
     | 
    
         
            +
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
            end 
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,111 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RubyProf
         
     | 
| 
      
 2 
     | 
    
         
            +
              class MethodInfo
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Comparable
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def <=>(other)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  if self.total_time < other.total_time
         
     | 
| 
      
 7 
     | 
    
         
            +
                    -1
         
     | 
| 
      
 8 
     | 
    
         
            +
                  elsif self.total_time > other.total_time
         
     | 
| 
      
 9 
     | 
    
         
            +
                    1
         
     | 
| 
      
 10 
     | 
    
         
            +
                  elsif self.min_depth < other.min_depth
         
     | 
| 
      
 11 
     | 
    
         
            +
                    1
         
     | 
| 
      
 12 
     | 
    
         
            +
                  elsif self.min_depth > other.min_depth
         
     | 
| 
      
 13 
     | 
    
         
            +
                    -1
         
     | 
| 
      
 14 
     | 
    
         
            +
                  else
         
     | 
| 
      
 15 
     | 
    
         
            +
                    -1 * (self.full_name <=> other.full_name)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def called
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @called ||= begin
         
     | 
| 
      
 21 
     | 
    
         
            +
                    call_infos.inject(0) do |sum, call_info|
         
     | 
| 
      
 22 
     | 
    
         
            +
                      sum += call_info.called
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def total_time
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @total_time ||= begin
         
     | 
| 
      
 29 
     | 
    
         
            +
                    call_infos.inject(0) do |sum, call_info|
         
     | 
| 
      
 30 
     | 
    
         
            +
                      sum += call_info.total_time
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                
         
     | 
| 
      
 35 
     | 
    
         
            +
                def self_time
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @self_time ||= begin
         
     | 
| 
      
 37 
     | 
    
         
            +
                    call_infos.inject(0) do |sum, call_info|
         
     | 
| 
      
 38 
     | 
    
         
            +
                      sum += call_info.self_time
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def wait_time
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @wait_time ||= begin
         
     | 
| 
      
 45 
     | 
    
         
            +
                    call_infos.inject(0) do |sum, call_info|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      sum += call_info.wait_time
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def children_time
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @children_time ||= begin
         
     | 
| 
      
 53 
     | 
    
         
            +
                    call_infos.inject(0) do |sum, call_info|
         
     | 
| 
      
 54 
     | 
    
         
            +
                      sum += call_info.children_time
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def min_depth
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @min_depth ||= call_infos.map do |call_info|
         
     | 
| 
      
 61 
     | 
    
         
            +
                    call_info.depth
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end.min
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def root?
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @root ||= begin
         
     | 
| 
      
 67 
     | 
    
         
            +
                    call_infos.find do |call_info|
         
     | 
| 
      
 68 
     | 
    
         
            +
                      not call_info.root?
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end.nil?
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def children
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @children ||= begin
         
     | 
| 
      
 75 
     | 
    
         
            +
                    call_infos.map do |call_info|
         
     | 
| 
      
 76 
     | 
    
         
            +
                      call_info.children
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end.flatten
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def aggregate_parents
         
     | 
| 
      
 82 
     | 
    
         
            +
                  # Group call info's based on their parents
         
     | 
| 
      
 83 
     | 
    
         
            +
                  groups = self.call_infos.inject(Hash.new) do |hash, call_info|
         
     | 
| 
      
 84 
     | 
    
         
            +
                    key = call_info.parent ? call_info.parent.target : self
         
     | 
| 
      
 85 
     | 
    
         
            +
                    (hash[key] ||= []) << call_info
         
     | 
| 
      
 86 
     | 
    
         
            +
                    hash
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  groups.map do |key, value|
         
     | 
| 
      
 90 
     | 
    
         
            +
                    AggregateCallInfo.new(value)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                def aggregate_children
         
     | 
| 
      
 95 
     | 
    
         
            +
                  # Group call info's based on their targets
         
     | 
| 
      
 96 
     | 
    
         
            +
                  groups = self.children.inject(Hash.new) do |hash, call_info|
         
     | 
| 
      
 97 
     | 
    
         
            +
                    key = call_info.target
         
     | 
| 
      
 98 
     | 
    
         
            +
                    (hash[key] ||= []) << call_info
         
     | 
| 
      
 99 
     | 
    
         
            +
                    hash
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  groups.map do |key, value|
         
     | 
| 
      
 103 
     | 
    
         
            +
                    AggregateCallInfo.new(value)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 108 
     | 
    
         
            +
                  full_name
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,146 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module RubyProf
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # Define a task library for profiling unit tests with ruby-prof.
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              # All of the options provided by
         
     | 
| 
      
 12 
     | 
    
         
            +
              # the Rake:TestTask are supported except the loader
         
     | 
| 
      
 13 
     | 
    
         
            +
              # which is set to ruby-prof.  For detailed information
         
     | 
| 
      
 14 
     | 
    
         
            +
              # please refer to the Rake:TestTask documentation.
         
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              # ruby-prof specific options include:
         
     | 
| 
      
 17 
     | 
    
         
            +
              #
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   output_dir - For each file specified an output 
         
     | 
| 
      
 19 
     | 
    
         
            +
              #                file with profile information will be
         
     | 
| 
      
 20 
     | 
    
         
            +
              #                written to the output directory.
         
     | 
| 
      
 21 
     | 
    
         
            +
              #                By default, the output directory is
         
     | 
| 
      
 22 
     | 
    
         
            +
              #                called "profile" and is created underneath
         
     | 
| 
      
 23 
     | 
    
         
            +
              #                the current working directory.
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              #   printer - Specifies the output printer.  Valid values include
         
     | 
| 
      
 26 
     | 
    
         
            +
              #             :flat, :graph, :graph_html and :call_tree.
         
     | 
| 
      
 27 
     | 
    
         
            +
              #
         
     | 
| 
      
 28 
     | 
    
         
            +
              #   min_percent - Methods that take less than the specified percent
         
     | 
| 
      
 29 
     | 
    
         
            +
              #                 will not be written out.
         
     | 
| 
      
 30 
     | 
    
         
            +
              #
         
     | 
| 
      
 31 
     | 
    
         
            +
              # Example:
         
     | 
| 
      
 32 
     | 
    
         
            +
              #   
         
     | 
| 
      
 33 
     | 
    
         
            +
              #   require 'ruby-prof/task'
         
     | 
| 
      
 34 
     | 
    
         
            +
              #   
         
     | 
| 
      
 35 
     | 
    
         
            +
              #   RubyProf::ProfileTask.new do |t|
         
     | 
| 
      
 36 
     | 
    
         
            +
              #     t.test_files = FileList['test/test*.rb']
         
     | 
| 
      
 37 
     | 
    
         
            +
              #     t.output_dir = "c:/temp"
         
     | 
| 
      
 38 
     | 
    
         
            +
              #     t.printer = :graph
         
     | 
| 
      
 39 
     | 
    
         
            +
              #     t.min_percent = 10
         
     | 
| 
      
 40 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 41 
     | 
    
         
            +
              #
         
     | 
| 
      
 42 
     | 
    
         
            +
              # If rake is invoked with a "TEST=filename" command line option,
         
     | 
| 
      
 43 
     | 
    
         
            +
              # then the list of test files will be overridden to include only the
         
     | 
| 
      
 44 
     | 
    
         
            +
              # filename specified on the command line.  This provides an easy way
         
     | 
| 
      
 45 
     | 
    
         
            +
              # to run just one test.
         
     | 
| 
      
 46 
     | 
    
         
            +
              #
         
     | 
| 
      
 47 
     | 
    
         
            +
              # If rake is invoked with a "TESTOPTS=options" command line option,
         
     | 
| 
      
 48 
     | 
    
         
            +
              # then the given options are passed to the test process after a
         
     | 
| 
      
 49 
     | 
    
         
            +
              # '--'.  This allows Test::Unit options to be passed to the test
         
     | 
| 
      
 50 
     | 
    
         
            +
              # suite.
         
     | 
| 
      
 51 
     | 
    
         
            +
              #
         
     | 
| 
      
 52 
     | 
    
         
            +
              # Examples:
         
     | 
| 
      
 53 
     | 
    
         
            +
              #
         
     | 
| 
      
 54 
     | 
    
         
            +
              #   rake profile                           # run tests normally
         
     | 
| 
      
 55 
     | 
    
         
            +
              #   rake profile TEST=just_one_file.rb     # run just one test file.
         
     | 
| 
      
 56 
     | 
    
         
            +
              #   rake profile TESTOPTS="-v"             # run in verbose mode
         
     | 
| 
      
 57 
     | 
    
         
            +
              #   rake profile TESTOPTS="--runner=fox"   # use the fox test runner
         
     | 
| 
      
 58 
     | 
    
         
            +
              
         
     | 
| 
      
 59 
     | 
    
         
            +
              class ProfileTask < Rake::TestTask
         
     | 
| 
      
 60 
     | 
    
         
            +
                attr_accessor :output_dir 
         
     | 
| 
      
 61 
     | 
    
         
            +
                attr_accessor :min_percent 
         
     | 
| 
      
 62 
     | 
    
         
            +
                attr_accessor :printer
         
     | 
| 
      
 63 
     | 
    
         
            +
                
         
     | 
| 
      
 64 
     | 
    
         
            +
                def initialize(name = :profile)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  super(name)
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                # Create the tasks defined by this task lib.
         
     | 
| 
      
 69 
     | 
    
         
            +
                def define
         
     | 
| 
      
 70 
     | 
    
         
            +
                  lib_path = @libs.join(File::PATH_SEPARATOR)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  desc "Profile" + (@name==:profile ? "" : " for #{@name}")
         
     | 
| 
      
 72 
     | 
    
         
            +
                  
         
     | 
| 
      
 73 
     | 
    
         
            +
                  task @name do
         
     | 
| 
      
 74 
     | 
    
         
            +
                    create_output_directory
         
     | 
| 
      
 75 
     | 
    
         
            +
                    
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @ruby_opts.unshift( "-I#{lib_path}" )
         
     | 
| 
      
 77 
     | 
    
         
            +
                    @ruby_opts.unshift( "-w" ) if @warning
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @ruby_opts.push("-S ruby-prof")
         
     | 
| 
      
 79 
     | 
    
         
            +
                    @ruby_opts.push("--printer #{@printer}")
         
     | 
| 
      
 80 
     | 
    
         
            +
                    @ruby_opts.push("--min_percent #{@min_percent}")
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    file_list.each do |file_path|  
         
     | 
| 
      
 83 
     | 
    
         
            +
                      run_script(file_path)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  self
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
                
         
     | 
| 
      
 89 
     | 
    
         
            +
                # Run script
         
     | 
| 
      
 90 
     | 
    
         
            +
                def run_script(script_path)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  run_code = ''
         
     | 
| 
      
 92 
     | 
    
         
            +
                  RakeFileUtils.verbose(@verbose) do
         
     | 
| 
      
 93 
     | 
    
         
            +
                    file_name = File.basename(script_path, File.extname(script_path))
         
     | 
| 
      
 94 
     | 
    
         
            +
                    case @printer
         
     | 
| 
      
 95 
     | 
    
         
            +
                      when :flat, :graph, :call_tree
         
     | 
| 
      
 96 
     | 
    
         
            +
                        file_name += ".txt"
         
     | 
| 
      
 97 
     | 
    
         
            +
                      when :graph_html
         
     | 
| 
      
 98 
     | 
    
         
            +
                        file_name += ".html"
         
     | 
| 
      
 99 
     | 
    
         
            +
                      else
         
     | 
| 
      
 100 
     | 
    
         
            +
                        file_name += ".txt"
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
                      
         
     | 
| 
      
 103 
     | 
    
         
            +
                    output_file_path = File.join(output_directory, file_name)
         
     | 
| 
      
 104 
     | 
    
         
            +
                      
         
     | 
| 
      
 105 
     | 
    
         
            +
                    command_line = @ruby_opts.join(" ") + 
         
     | 
| 
      
 106 
     | 
    
         
            +
                                  " --file=" + output_file_path +
         
     | 
| 
      
 107 
     | 
    
         
            +
                                  " " + script_path
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    puts "ruby " + command_line 
         
     | 
| 
      
 110 
     | 
    
         
            +
                    # We have to catch the exeption to continue on.  However,
         
     | 
| 
      
 111 
     | 
    
         
            +
                    # the error message will have been output to STDERR
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # already by the time we get here so we don't have to
         
     | 
| 
      
 113 
     | 
    
         
            +
                    # do that again
         
     | 
| 
      
 114 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 115 
     | 
    
         
            +
                      ruby command_line
         
     | 
| 
      
 116 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 117 
     | 
    
         
            +
                      STDOUT << e << "\n"
         
     | 
| 
      
 118 
     | 
    
         
            +
                      STDOUT.flush
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    puts ""
         
     | 
| 
      
 121 
     | 
    
         
            +
                    puts ""
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                def output_directory
         
     | 
| 
      
 126 
     | 
    
         
            +
                  File.expand_path(@output_dir)
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
                
         
     | 
| 
      
 129 
     | 
    
         
            +
                def create_output_directory
         
     | 
| 
      
 130 
     | 
    
         
            +
                  if not File.exist?(output_directory)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    Dir.mkdir(output_directory)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                def clean_output_directory
         
     | 
| 
      
 136 
     | 
    
         
            +
                  if File.exist?(output_directory)
         
     | 
| 
      
 137 
     | 
    
         
            +
                    files = Dir.glob(output_directory + '/*')
         
     | 
| 
      
 138 
     | 
    
         
            +
                    FileUtils.rm(files)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
                
         
     | 
| 
      
 142 
     | 
    
         
            +
                def option_list # :nodoc:
         
     | 
| 
      
 143 
     | 
    
         
            +
                  ENV['OPTIONS'] || @options.join(" ") || ""
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Now load ruby-prof and away we go
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'ruby-prof'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'benchmark'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module RubyProf
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Test
         
     | 
| 
      
 8 
     | 
    
         
            +
                PROFILE_OPTIONS = {
         
     | 
| 
      
 9 
     | 
    
         
            +
                  :measure_modes => [RubyProf::PROCESS_TIME],
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :count => 10,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  :printers => [RubyProf::FlatPrinter, RubyProf::GraphHtmlPrinter],
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :min_percent => 0.05,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  :output_dir => Dir.pwd }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def output_dir
         
     | 
| 
      
 16 
     | 
    
         
            +
                  PROFILE_OPTIONS[:output_dir]
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      
         
     | 
| 
      
 19 
     | 
    
         
            +
                def run(result)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  return if @method_name.to_s == "default_test"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  yield(self.class::STARTED, name)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @_result = result
         
     | 
| 
      
 24 
     | 
    
         
            +
                  run_warmup
         
     | 
| 
      
 25 
     | 
    
         
            +
                  PROFILE_OPTIONS[:measure_modes].each do |measure_mode|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    data = run_profile(measure_mode)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    report_profile(data, measure_mode)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    result.add_run
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  yield(self.class::FINISHED, name)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def run_test
         
     | 
| 
      
 34 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 35 
     | 
    
         
            +
                    setup
         
     | 
| 
      
 36 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 37 
     | 
    
         
            +
                  rescue ::Test::Unit::AssertionFailedError => e
         
     | 
| 
      
 38 
     | 
    
         
            +
                    add_failure(e.message, e.backtrace)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  rescue StandardError, ScriptError
         
     | 
| 
      
 40 
     | 
    
         
            +
                    add_error($!)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 42 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 43 
     | 
    
         
            +
                      teardown
         
     | 
| 
      
 44 
     | 
    
         
            +
                    rescue ::Test::Unit::AssertionFailedError => e
         
     | 
| 
      
 45 
     | 
    
         
            +
                      add_failure(e.message, e.backtrace)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    rescue StandardError, ScriptError
         
     | 
| 
      
 47 
     | 
    
         
            +
                      add_error($!)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def run_warmup
         
     | 
| 
      
 53 
     | 
    
         
            +
                  print "\n#{self.class.name}##{method_name}"
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  run_test do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    bench = Benchmark.realtime do
         
     | 
| 
      
 57 
     | 
    
         
            +
                      __send__(@method_name)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    puts " (%.2fs warmup)" % bench
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                def run_profile(measure_mode)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  RubyProf.measure_mode = measure_mode
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  print '  '
         
     | 
| 
      
 67 
     | 
    
         
            +
                  PROFILE_OPTIONS[:count].times do |i|
         
     | 
| 
      
 68 
     | 
    
         
            +
                    run_test do
         
     | 
| 
      
 69 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 70 
     | 
    
         
            +
                        print '.'
         
     | 
| 
      
 71 
     | 
    
         
            +
                        $stdout.flush
         
     | 
| 
      
 72 
     | 
    
         
            +
                        GC.disable
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                        RubyProf.resume do
         
     | 
| 
      
 75 
     | 
    
         
            +
                          __send__(@method_name)
         
     | 
| 
      
 76 
     | 
    
         
            +
                        end
         
     | 
| 
      
 77 
     | 
    
         
            +
                      ensure
         
     | 
| 
      
 78 
     | 
    
         
            +
                        GC.enable
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  data = RubyProf.stop
         
     | 
| 
      
 84 
     | 
    
         
            +
                  bench = data.threads.values.inject(0) do |total, method_infos|
         
     | 
| 
      
 85 
     | 
    
         
            +
                    top = method_infos.max
         
     | 
| 
      
 86 
     | 
    
         
            +
                    total += top.total_time
         
     | 
| 
      
 87 
     | 
    
         
            +
                    total
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  puts "\n  #{measure_mode_name(measure_mode)}: #{format_profile_total(bench, measure_mode)}\n"
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  data
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def format_profile_total(total, measure_mode)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  case measure_mode
         
     | 
| 
      
 97 
     | 
    
         
            +
                    when RubyProf::PROCESS_TIME, RubyProf::WALL_TIME
         
     | 
| 
      
 98 
     | 
    
         
            +
                      "%.2f seconds" % total
         
     | 
| 
      
 99 
     | 
    
         
            +
                    when RubyProf::MEMORY
         
     | 
| 
      
 100 
     | 
    
         
            +
                      "%.2f kilobytes" % total
         
     | 
| 
      
 101 
     | 
    
         
            +
                    when RubyProf::ALLOCATIONS
         
     | 
| 
      
 102 
     | 
    
         
            +
                      "%d allocations" % total
         
     | 
| 
      
 103 
     | 
    
         
            +
                    else
         
     | 
| 
      
 104 
     | 
    
         
            +
                      "%.2f #{measure_mode}"
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                def report_profile(data, measure_mode)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  PROFILE_OPTIONS[:printers].each do |printer_klass|
         
     | 
| 
      
 110 
     | 
    
         
            +
                    printer = printer_klass.new(data)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # Makes sure the output directory exits
         
     | 
| 
      
 113 
     | 
    
         
            +
                    FileUtils.mkdir_p(output_dir)
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                    # Open the file
         
     | 
| 
      
 116 
     | 
    
         
            +
                    file_name = report_filename(printer, measure_mode)
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    File.open(file_name, 'wb') do |file|
         
     | 
| 
      
 119 
     | 
    
         
            +
                      printer.print(file, PROFILE_OPTIONS)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                # The report filename is test_name + measure_mode + report_type
         
     | 
| 
      
 125 
     | 
    
         
            +
                def report_filename(printer, measure_mode)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  suffix =
         
     | 
| 
      
 127 
     | 
    
         
            +
                    case printer
         
     | 
| 
      
 128 
     | 
    
         
            +
                      when RubyProf::FlatPrinter; 'flat.txt'
         
     | 
| 
      
 129 
     | 
    
         
            +
                      when RubyProf::GraphPrinter; 'graph.txt'
         
     | 
| 
      
 130 
     | 
    
         
            +
                      when RubyProf::GraphHtmlPrinter; 'graph.html'
         
     | 
| 
      
 131 
     | 
    
         
            +
                      when RubyProf::CallTreePrinter; 'tree.txt'
         
     | 
| 
      
 132 
     | 
    
         
            +
                      else printer.to_s.downcase
         
     | 
| 
      
 133 
     | 
    
         
            +
                    end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  "#{output_dir}/#{method_name}_#{measure_mode_name(measure_mode)}_#{suffix}"
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                def measure_mode_name(measure_mode)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  case measure_mode
         
     | 
| 
      
 140 
     | 
    
         
            +
                    when RubyProf::PROCESS_TIME; 'process_time'
         
     | 
| 
      
 141 
     | 
    
         
            +
                    when RubyProf::WALL_TIME; 'wall_time'
         
     | 
| 
      
 142 
     | 
    
         
            +
                    when RubyProf::MEMORY; 'memory'
         
     | 
| 
      
 143 
     | 
    
         
            +
                    when RubyProf::ALLOCATIONS; 'allocations'
         
     | 
| 
      
 144 
     | 
    
         
            +
                    else "measure#{measure_mode}"
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            end
         
     |