ruby-prof 1.1.0

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +532 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +5 -0
  5. data/Rakefile +110 -0
  6. data/bin/ruby-prof +380 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +36 -0
  9. data/ext/ruby_prof/rp_allocation.c +279 -0
  10. data/ext/ruby_prof/rp_allocation.h +31 -0
  11. data/ext/ruby_prof/rp_call_info.c +271 -0
  12. data/ext/ruby_prof/rp_call_info.h +35 -0
  13. data/ext/ruby_prof/rp_measure_allocations.c +52 -0
  14. data/ext/ruby_prof/rp_measure_memory.c +42 -0
  15. data/ext/ruby_prof/rp_measure_process_time.c +67 -0
  16. data/ext/ruby_prof/rp_measure_wall_time.c +62 -0
  17. data/ext/ruby_prof/rp_measurement.c +230 -0
  18. data/ext/ruby_prof/rp_measurement.h +50 -0
  19. data/ext/ruby_prof/rp_method.c +630 -0
  20. data/ext/ruby_prof/rp_method.h +70 -0
  21. data/ext/ruby_prof/rp_profile.c +895 -0
  22. data/ext/ruby_prof/rp_profile.h +37 -0
  23. data/ext/ruby_prof/rp_stack.c +196 -0
  24. data/ext/ruby_prof/rp_stack.h +56 -0
  25. data/ext/ruby_prof/rp_thread.c +337 -0
  26. data/ext/ruby_prof/rp_thread.h +36 -0
  27. data/ext/ruby_prof/ruby_prof.c +48 -0
  28. data/ext/ruby_prof/ruby_prof.h +17 -0
  29. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  30. data/ext/ruby_prof/vc/ruby_prof.vcxproj +143 -0
  31. data/lib/ruby-prof.rb +52 -0
  32. data/lib/ruby-prof/assets/call_stack_printer.html.erb +713 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  34. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  35. data/lib/ruby-prof/call_info.rb +57 -0
  36. data/lib/ruby-prof/call_info_visitor.rb +38 -0
  37. data/lib/ruby-prof/compatibility.rb +109 -0
  38. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  39. data/lib/ruby-prof/measurement.rb +14 -0
  40. data/lib/ruby-prof/method_info.rb +90 -0
  41. data/lib/ruby-prof/printers/abstract_printer.rb +127 -0
  42. data/lib/ruby-prof/printers/call_info_printer.rb +51 -0
  43. data/lib/ruby-prof/printers/call_stack_printer.rb +182 -0
  44. data/lib/ruby-prof/printers/call_tree_printer.rb +151 -0
  45. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  46. data/lib/ruby-prof/printers/flat_printer.rb +52 -0
  47. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
  48. data/lib/ruby-prof/printers/graph_printer.rb +114 -0
  49. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  50. data/lib/ruby-prof/profile.rb +33 -0
  51. data/lib/ruby-prof/rack.rb +171 -0
  52. data/lib/ruby-prof/task.rb +147 -0
  53. data/lib/ruby-prof/thread.rb +35 -0
  54. data/lib/ruby-prof/version.rb +3 -0
  55. data/lib/unprof.rb +10 -0
  56. data/ruby-prof.gemspec +58 -0
  57. data/test/abstract_printer_test.rb +26 -0
  58. data/test/alias_test.rb +129 -0
  59. data/test/basic_test.rb +129 -0
  60. data/test/call_info_visitor_test.rb +31 -0
  61. data/test/duplicate_names_test.rb +32 -0
  62. data/test/dynamic_method_test.rb +53 -0
  63. data/test/enumerable_test.rb +21 -0
  64. data/test/exceptions_test.rb +24 -0
  65. data/test/exclude_methods_test.rb +146 -0
  66. data/test/exclude_threads_test.rb +53 -0
  67. data/test/fiber_test.rb +73 -0
  68. data/test/gc_test.rb +96 -0
  69. data/test/line_number_test.rb +161 -0
  70. data/test/marshal_test.rb +119 -0
  71. data/test/measure_allocations.rb +30 -0
  72. data/test/measure_allocations_test.rb +385 -0
  73. data/test/measure_allocations_trace_test.rb +385 -0
  74. data/test/measure_memory_trace_test.rb +756 -0
  75. data/test/measure_process_time_test.rb +849 -0
  76. data/test/measure_times.rb +54 -0
  77. data/test/measure_wall_time_test.rb +459 -0
  78. data/test/multi_printer_test.rb +71 -0
  79. data/test/no_method_class_test.rb +15 -0
  80. data/test/parser_timings.rb +24 -0
  81. data/test/pause_resume_test.rb +166 -0
  82. data/test/prime.rb +56 -0
  83. data/test/printer_call_stack_test.rb +28 -0
  84. data/test/printer_call_tree_test.rb +31 -0
  85. data/test/printer_flat_test.rb +68 -0
  86. data/test/printer_graph_html_test.rb +60 -0
  87. data/test/printer_graph_test.rb +41 -0
  88. data/test/printers_test.rb +141 -0
  89. data/test/printing_recursive_graph_test.rb +81 -0
  90. data/test/rack_test.rb +157 -0
  91. data/test/recursive_test.rb +210 -0
  92. data/test/singleton_test.rb +38 -0
  93. data/test/stack_printer_test.rb +64 -0
  94. data/test/start_stop_test.rb +109 -0
  95. data/test/test_helper.rb +24 -0
  96. data/test/thread_test.rb +144 -0
  97. data/test/unique_call_path_test.rb +190 -0
  98. data/test/yarv_test.rb +56 -0
  99. metadata +191 -0
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Generates flat[link:files/examples/flat_txt.html] profile reports as text.
5
+ # To use the flat printer:
6
+ #
7
+ # result = RubyProf.profile do
8
+ # [code to profile]
9
+ # end
10
+ #
11
+ # printer = RubyProf::FlatPrinter.new(result)
12
+ # printer.print(STDOUT, {})
13
+ #
14
+ class FlatPrinter < AbstractPrinter
15
+ # Override for this printer to sort by self time by default
16
+ def sort_method
17
+ @options[:sort_method] || :self_time
18
+ end
19
+
20
+ private
21
+
22
+ def print_column_headers
23
+ @output << " %self total self wait child calls name location\n"
24
+ end
25
+
26
+ def print_methods(thread)
27
+ total_time = thread.total_time
28
+ methods = thread.methods.sort_by(&sort_method).reverse
29
+
30
+ sum = 0
31
+ methods.each do |method|
32
+ self_percent = (method.self_time / total_time) * 100
33
+ next if self_percent < min_percent
34
+
35
+ sum += method.self_time
36
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
37
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
38
+
39
+ @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%-30s %s\n" % [
40
+ method.self_time / total_time * 100, # %self
41
+ method.total_time, # total
42
+ method.self_time, # self
43
+ method.wait_time, # wait
44
+ method.children_time, # children
45
+ method.called, # calls
46
+ method.recursive? ? "*" : " ", # cycle
47
+ method.full_name, # method_name]
48
+ method_location(method)] # location]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ module RubyProf
6
+ # Generates graph[link:files/examples/graph_html.html] profile reports as html.
7
+ # To use the graph html printer:
8
+ #
9
+ # result = RubyProf.profile do
10
+ # [code to profile]
11
+ # end
12
+ #
13
+ # printer = RubyProf::GraphHtmlPrinter.new(result)
14
+ # printer.print(STDOUT, :min_percent=>0)
15
+ #
16
+ # The Graph printer takes the following options in its print methods:
17
+
18
+ class GraphHtmlPrinter < AbstractPrinter
19
+ include ERB::Util
20
+
21
+ def setup_options(options)
22
+ super(options)
23
+ @erb = ERB.new(self.template)
24
+ end
25
+
26
+ def print(output = STDOUT, options = {})
27
+ setup_options(options)
28
+ output << @erb.result(binding)
29
+ end
30
+
31
+ # Creates a link to a method. Note that we do not create
32
+ # links to methods which are under the min_perecent
33
+ # specified by the user, since they will not be
34
+ # printed out.
35
+ def create_link(thread, overall_time, method)
36
+ total_percent = (method.total_time/overall_time) * 100
37
+ if total_percent < min_percent
38
+ # Just return name
39
+ h method.full_name
40
+ else
41
+ href = '#' + method_href(thread, method)
42
+ "<a href=\"#{href}\">#{h method.full_name}</a>"
43
+ end
44
+ end
45
+
46
+ def method_href(thread, method)
47
+ h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread.fiber_id.to_s)
48
+ end
49
+
50
+ def file_link(path, linenum)
51
+ if path.nil?
52
+ ""
53
+ else
54
+ srcfile = File.expand_path(path)
55
+ "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
56
+ end
57
+ end
58
+
59
+ def template
60
+ open_asset('graph_printer.html.erb')
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
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)
12
+ # printer.print(STDOUT, {})
13
+ #
14
+ # The constructor takes two arguments. See the README
15
+
16
+ class GraphPrinter < AbstractPrinter
17
+ PERCENTAGE_WIDTH = 8
18
+ TIME_WIDTH = 11
19
+ CALL_WIDTH = 17
20
+
21
+ private
22
+
23
+ def sort_method
24
+ @options[:sort_method] || :total_time
25
+ end
26
+
27
+ def print_header(thread)
28
+ @output << "Measure Mode: %s\n" % RubyProf.measure_mode_string
29
+ @output << "Thread ID: #{thread.id}\n"
30
+ @output << "Fiber ID: #{thread.fiber_id}\n"
31
+ @output << "Total Time: #{thread.total_time}\n"
32
+ @output << "Sort by: #{sort_method}\n"
33
+ @output << "\n"
34
+
35
+ # 1 is for % sign
36
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
37
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
38
+ @output << sprintf("%#{TIME_WIDTH}s", "total")
39
+ @output << sprintf("%#{TIME_WIDTH}s", "self")
40
+ @output << sprintf("%#{TIME_WIDTH}s", "wait")
41
+ @output << sprintf("%#{TIME_WIDTH}s", "child")
42
+ @output << sprintf("%#{CALL_WIDTH}s", "calls")
43
+ @output << " name"
44
+ @output << " location"
45
+ @output << "\n"
46
+ end
47
+
48
+ def print_methods(thread)
49
+ total_time = thread.total_time
50
+ # Sort methods from longest to shortest total time
51
+ methods = thread.methods.sort_by(&sort_method)
52
+
53
+ # Print each method in total time order
54
+ methods.reverse_each do |method|
55
+ total_percentage = (method.total_time/total_time) * 100
56
+ next if total_percentage < min_percent
57
+
58
+ self_percentage = (method.self_time/total_time) * 100
59
+
60
+ @output << "-" * 150 << "\n"
61
+ print_parents(thread, method)
62
+
63
+ # 1 is for % sign
64
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", total_percentage)
65
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", self_percentage)
66
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
67
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
68
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
69
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.children_time)
70
+ @output << sprintf("%#{CALL_WIDTH}i", method.called)
71
+ @output << sprintf(" %s", method.recursive? ? "*" : " ")
72
+ @output << sprintf("%-30s", method.full_name)
73
+ @output << sprintf(" %s", method_location(method))
74
+ @output << "\n"
75
+
76
+ print_children(method)
77
+ end
78
+ end
79
+
80
+ def print_parents(thread, method)
81
+ return if method.root?
82
+ method.callers.sort_by(&:total_time).each do |caller|
83
+ @output << " " * 2 * PERCENTAGE_WIDTH
84
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.total_time)
85
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.self_time)
86
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.wait_time)
87
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.children_time)
88
+
89
+ call_called = "#{caller.called}/#{method.called}"
90
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
91
+ @output << sprintf(" %s", caller.parent.full_name)
92
+ @output << "\n"
93
+ end
94
+ end
95
+
96
+ def print_children(method)
97
+ method.callees.sort_by(&:total_time).reverse.each do |child|
98
+ # Get children method
99
+
100
+ @output << " " * 2 * PERCENTAGE_WIDTH
101
+
102
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.total_time)
103
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.self_time)
104
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.wait_time)
105
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.children_time)
106
+
107
+ call_called = "#{child.called}/#{child.target.called}"
108
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
109
+ @output << sprintf(" %s", child.target.full_name)
110
+ @output << "\n"
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,127 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Helper class to simplify printing profiles of several types from
5
+ # one profiling run. Currently prints a flat profile, a callgrind
6
+ # profile, a call stack profile and a graph profile.
7
+ class MultiPrinter
8
+ def initialize(result, printers = [:flat, :graph_html])
9
+ @flat_printer = FlatPrinter.new(result) if printers.include?(:flat)
10
+
11
+ @graph_printer = GraphPrinter.new(result) if printers.include?(:graph)
12
+ @graph_html_printer = GraphHtmlPrinter.new(result) if printers.include?(:graph_html)
13
+
14
+ @tree_printer = CallTreePrinter.new(result) if printers.include?(:tree)
15
+ @call_info_printer = CallInfoPrinter.new(result) if printers.include?(:call_info)
16
+
17
+ @stack_printer = CallStackPrinter.new(result) if printers.include?(:stack)
18
+ @dot_printer = DotPrinter.new(result) if printers.include?(:dot)
19
+ end
20
+
21
+ def self.needs_dir?
22
+ true
23
+ end
24
+
25
+ # create profile files under options[:path] or the current
26
+ # directory. options[:profile] is used as the base name for the
27
+ # profile file, defaults to "profile".
28
+ def print(options)
29
+ validate_print_params(options)
30
+
31
+ @profile = options.delete(:profile) || "profile"
32
+ @directory = options.delete(:path) || File.expand_path(".")
33
+
34
+ print_to_flat(options) if @flat_printer
35
+
36
+ print_to_graph(options) if @graph_printer
37
+ print_to_graph_html(options) if @graph_html_printer
38
+
39
+ print_to_stack(options) if @stack_printer
40
+ print_to_call_info(options) if @call_info_printer
41
+ print_to_tree(options) if @tree_printer
42
+ print_to_dot(options) if @dot_printer
43
+ end
44
+
45
+ # the name of the flat profile file
46
+ def flat_report
47
+ "#{@directory}/#{@profile}.flat.txt"
48
+ end
49
+
50
+ # the name of the graph profile file
51
+ def graph_report
52
+ "#{@directory}/#{@profile}.graph.txt"
53
+ end
54
+
55
+ def graph_html_report
56
+ "#{@directory}/#{@profile}.graph.html"
57
+ end
58
+
59
+ # the name of the callinfo profile file
60
+ def call_info_report
61
+ "#{@directory}/#{@profile}.call_info.txt"
62
+ end
63
+
64
+ # the name of the callgrind profile file
65
+ def tree_report
66
+ "#{@directory}/#{@profile}.callgrind.out.#{$$}"
67
+ end
68
+
69
+ # the name of the call stack profile file
70
+ def stack_report
71
+ "#{@directory}/#{@profile}.stack.html"
72
+ end
73
+
74
+ # the name of the call stack profile file
75
+ def dot_report
76
+ "#{@directory}/#{@profile}.dot"
77
+ end
78
+
79
+ def print_to_flat(options)
80
+ File.open(flat_report, "wb") do |file|
81
+ @flat_printer.print(file, options)
82
+ end
83
+ end
84
+
85
+ def print_to_graph(options)
86
+ File.open(graph_report, "wb") do |file|
87
+ @graph_printer.print(file, options)
88
+ end
89
+ end
90
+
91
+ def print_to_graph_html(options)
92
+ File.open(graph_html_report, "wb") do |file|
93
+ @graph_html_printer.print(file, options)
94
+ end
95
+ end
96
+
97
+ def print_to_call_info(options)
98
+ File.open(call_info_report, "wb") do |file|
99
+ @call_info_printer.print(file, options)
100
+ end
101
+ end
102
+
103
+ def print_to_tree(options)
104
+ @tree_printer.print(options.merge(:path => @directory, :profile => @profile))
105
+ end
106
+
107
+ def print_to_stack(options)
108
+ File.open(stack_report, "wb") do |file|
109
+ @stack_printer.print(file, options.merge(:graph => "#{@profile}.graph.html"))
110
+ end
111
+ end
112
+
113
+ def print_to_dot(options)
114
+ File.open(dot_report, "wb") do |file|
115
+ @dot_printer.print(file, options)
116
+ end
117
+ end
118
+
119
+ def validate_print_params(options)
120
+ if options.is_a?(IO)
121
+ raise ArgumentError, "#{self.class.name}#print cannot print to IO objects"
122
+ elsif !options.is_a?(Hash)
123
+ raise ArgumentError, "#{self.class.name}#print requires an options hash"
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ruby-prof/exclude_common_methods'
4
+
5
+ module RubyProf
6
+ class Profile
7
+ # :nodoc:
8
+ def measure_mode_string
9
+ case self.measure_mode
10
+ when WALL_TIME then "wall_time"
11
+ when PROCESS_TIME then "process_time"
12
+ when ALLOCATIONS then "allocations"
13
+ when MEMORY then "memory"
14
+ end
15
+ end
16
+
17
+ # Hides methods that, when represented as a call graph, have
18
+ # extremely large in and out degrees and make navigation impossible.
19
+ def exclude_common_methods!
20
+ ExcludeCommonMethods.apply!(self)
21
+ end
22
+
23
+ def exclude_methods!(mod, *method_or_methods)
24
+ [method_or_methods].flatten.each do |name|
25
+ exclude_method!(mod, name)
26
+ end
27
+ end
28
+
29
+ def exclude_singleton_methods!(mod, *method_or_methods)
30
+ exclude_methods!(mod.singleton_class, *method_or_methods)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,171 @@
1
+ # encoding: utf-8
2
+ require 'tmpdir'
3
+
4
+ module Rack
5
+ class RubyProf
6
+ def initialize(app, options = {})
7
+ @app = app
8
+
9
+ options[:min_percent] ||= 1
10
+
11
+ options[:path] ||= Dir.tmpdir
12
+ FileUtils.mkdir_p(options[:path])
13
+
14
+ @skip_paths = options[:skip_paths] || [%r{^/assets}, %r{\.(css|js|png|jpeg|jpg|gif)$}]
15
+ @only_paths = options[:only_paths]
16
+
17
+ @max_requests = options[:max_requests]
18
+
19
+ @options = options
20
+ end
21
+
22
+ def call(env)
23
+ request = Rack::Request.new(env)
24
+
25
+ if should_profile?(request.path)
26
+ profiler.resume
27
+ begin
28
+ result = @app.call(env)
29
+ ensure
30
+ profiler.pause
31
+ end
32
+
33
+ if profiler.max_requests_reached?
34
+ prefix = if aggregate_requests?
35
+ nil
36
+ else
37
+ request.path.gsub('/', '-')[1..-1]
38
+ end
39
+
40
+ profiler.print!(prefix)
41
+ delete_profiler!
42
+ end
43
+
44
+ result
45
+ else
46
+ @app.call(env)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ class RackProfiler
53
+ def initialize(options)
54
+ @options = options
55
+
56
+ @profile = ::RubyProf::Profile.new(profiling_options)
57
+ @profile.start
58
+ @profile.pause
59
+
60
+ @printer_klasses = options[:printers] || default_printers
61
+
62
+ @tmpdir = options[:path]
63
+
64
+ @max_requests = options[:max_requests] || 1
65
+ @requests_count = 0
66
+
67
+ @printed = false
68
+ # if running across multiple requests, we want to make sure that the
69
+ # ongoing profile is not lost if the process shuts down before the
70
+ # max request count is reached
71
+ ObjectSpace.define_finalizer(self, proc { print! })
72
+ end
73
+
74
+ def resume
75
+ @profile.resume
76
+ end
77
+
78
+ def pause
79
+ @profile.pause
80
+ @requests_count += 1
81
+ end
82
+
83
+ def max_requests_reached?
84
+ @requests_count >= @max_requests
85
+ end
86
+
87
+ def print!(prefix = nil)
88
+ return false if @printed || @requests_count == 0
89
+
90
+ data = @profile.stop
91
+
92
+ prefix ||= "multi-requests-#{@requests_count}"
93
+
94
+ @printer_klasses.each do |printer_klass, base_name|
95
+ printer = printer_klass.new(data)
96
+
97
+ if base_name.respond_to?(:call)
98
+ base_name = base_name.call
99
+ end
100
+
101
+ if printer_klass == ::RubyProf::MultiPrinter \
102
+ || printer_klass == ::RubyProf::CallTreePrinter
103
+ printer.print(@options.merge(:profile => "#{prefix}-#{base_name}"))
104
+ else
105
+ file_name = ::File.join(@tmpdir, "#{prefix}-#{base_name}")
106
+ ::File.open(file_name, 'wb') do |file|
107
+ printer.print(file, @options)
108
+ end
109
+ end
110
+ end
111
+
112
+ @printed = true
113
+ end
114
+
115
+ private
116
+
117
+ def profiling_options
118
+ options = {}
119
+ options[:measure_mode] = ::RubyProf.measure_mode
120
+ options[:exclude_threads] =
121
+ if @options[:ignore_existing_threads]
122
+ Thread.list.select{|t| t != Thread.current}
123
+ else
124
+ ::RubyProf.exclude_threads
125
+ end
126
+ if @options[:request_thread_only]
127
+ options[:include_threads] = [Thread.current]
128
+ end
129
+ options
130
+ end
131
+
132
+ def default_printers
133
+ {::RubyProf::FlatPrinter => 'flat.txt',
134
+ ::RubyProf::GraphPrinter => 'graph.txt',
135
+ ::RubyProf::GraphHtmlPrinter => 'graph.html',
136
+ ::RubyProf::CallStackPrinter => 'call_stack.html'}
137
+ end
138
+ end
139
+
140
+ def profiler
141
+ if aggregate_requests?
142
+ @@_shared_profiler ||= RackProfiler.new(@options)
143
+ else
144
+ @_profiler ||= RackProfiler.new(@options)
145
+ end
146
+ end
147
+
148
+ def delete_profiler!
149
+ if aggregate_requests?
150
+ @@_shared_profiler.print! if @@_shared_profiler
151
+ @@_shared_profiler = nil
152
+ else
153
+ @_profiler = nil
154
+ end
155
+ end
156
+
157
+ def aggregate_requests?
158
+ !@max_requests.nil?
159
+ end
160
+
161
+ def should_profile?(path)
162
+ return false if paths_match?(path, @skip_paths)
163
+
164
+ @only_paths ? paths_match?(path, @only_paths) : true
165
+ end
166
+
167
+ def paths_match?(path, paths)
168
+ paths.any? { |skip_path| skip_path =~ path }
169
+ end
170
+ end
171
+ end