ruby-prof 0.16.2 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGES +15 -0
- data/README.rdoc +36 -5
- data/bin/ruby-prof +7 -2
- data/doc/LICENSE.html +2 -1
- data/doc/README_rdoc.html +42 -8
- data/doc/Rack.html +2 -1
- data/doc/Rack/RubyProf.html +25 -18
- data/doc/Rack/RubyProf/RackProfiler.html +343 -0
- data/doc/RubyProf.html +14 -2
- data/doc/RubyProf/AbstractPrinter.html +91 -12
- data/doc/RubyProf/AggregateCallInfo.html +2 -1
- data/doc/RubyProf/CallInfo.html +18 -78
- data/doc/RubyProf/CallInfoPrinter.html +2 -1
- data/doc/RubyProf/CallInfoVisitor.html +2 -1
- data/doc/RubyProf/CallStackPrinter.html +35 -29
- data/doc/RubyProf/CallTreePrinter.html +98 -14
- data/doc/RubyProf/Cmd.html +11 -5
- data/doc/RubyProf/DeprecationWarnings.html +148 -0
- data/doc/RubyProf/DotPrinter.html +2 -1
- data/doc/RubyProf/FlatPrinter.html +2 -1
- data/doc/RubyProf/FlatPrinterWithLineNumbers.html +7 -5
- data/doc/RubyProf/GraphHtmlPrinter.html +18 -12
- data/doc/RubyProf/GraphPrinter.html +2 -1
- data/doc/RubyProf/MethodInfo.html +19 -88
- data/doc/RubyProf/MultiPrinter.html +231 -17
- data/doc/RubyProf/Profile.html +184 -39
- data/doc/RubyProf/Profile/ExcludeCommonMethods.html +411 -0
- data/doc/RubyProf/Profile/LegacyMethodElimination.html +158 -0
- data/doc/RubyProf/ProfileTask.html +2 -1
- data/doc/RubyProf/Thread.html +4 -39
- data/doc/created.rid +21 -19
- data/doc/css/fonts.css +6 -6
- data/doc/examples/flat_txt.html +2 -1
- data/doc/examples/graph_html.html +2 -1
- data/doc/examples/graph_txt.html +2 -1
- data/doc/index.html +47 -7
- data/doc/js/darkfish.js +7 -7
- data/doc/js/search_index.js +1 -1
- data/doc/js/search_index.js.gz +0 -0
- data/doc/js/searcher.js +1 -0
- data/doc/js/searcher.js.gz +0 -0
- data/doc/table_of_contents.html +190 -80
- data/ext/ruby_prof/extconf.rb +4 -0
- data/ext/ruby_prof/rp_call_info.c +19 -1
- data/ext/ruby_prof/rp_call_info.h +8 -3
- data/ext/ruby_prof/rp_method.c +282 -57
- data/ext/ruby_prof/rp_method.h +28 -5
- data/ext/ruby_prof/rp_stack.c +69 -24
- data/ext/ruby_prof/rp_stack.h +21 -9
- data/ext/ruby_prof/rp_thread.c +4 -1
- data/ext/ruby_prof/ruby_prof.c +142 -39
- data/ext/ruby_prof/ruby_prof.h +3 -0
- data/lib/ruby-prof.rb +10 -0
- data/lib/ruby-prof/call_info.rb +0 -11
- data/lib/ruby-prof/method_info.rb +4 -12
- data/lib/ruby-prof/printers/abstract_printer.rb +19 -1
- data/lib/ruby-prof/printers/call_info_printer.rb +1 -1
- data/lib/ruby-prof/printers/call_stack_printer.rb +9 -4
- data/lib/ruby-prof/printers/call_tree_printer.rb +15 -2
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +23 -4
- data/lib/ruby-prof/printers/graph_html_printer.rb +10 -5
- data/lib/ruby-prof/printers/graph_printer.rb +2 -2
- data/lib/ruby-prof/printers/multi_printer.rb +44 -18
- data/lib/ruby-prof/profile.rb +13 -42
- data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
- data/lib/ruby-prof/profile/legacy_method_elimination.rb +49 -0
- data/lib/ruby-prof/rack.rb +130 -51
- data/lib/ruby-prof/thread.rb +0 -6
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +4 -3
- data/test/aggregate_test.rb +1 -1
- data/test/exclude_methods_test.rb +146 -0
- data/test/line_number_test.rb +12 -3
- data/test/multi_printer_test.rb +23 -2
- data/test/no_method_class_test.rb +1 -1
- data/test/printers_test.rb +21 -1
- data/test/rack_test.rb +64 -0
- data/test/recursive_test.rb +15 -15
- data/test/test_helper.rb +11 -0
- metadata +20 -13
data/ext/ruby_prof/ruby_prof.h
CHANGED
@@ -42,11 +42,14 @@ typedef struct
|
|
42
42
|
{
|
43
43
|
VALUE running;
|
44
44
|
VALUE paused;
|
45
|
+
|
45
46
|
prof_measurer_t* measurer;
|
46
47
|
VALUE threads;
|
48
|
+
|
47
49
|
st_table* threads_tbl;
|
48
50
|
st_table* exclude_threads_tbl;
|
49
51
|
st_table* include_threads_tbl;
|
52
|
+
st_table* exclude_methods_tbl;
|
50
53
|
thread_data_t* last_thread_data;
|
51
54
|
double measurement_at_pause_resume;
|
52
55
|
int merge_fibers;
|
data/lib/ruby-prof.rb
CHANGED
@@ -8,6 +8,16 @@ rescue LoadError
|
|
8
8
|
require "ruby_prof.so"
|
9
9
|
end
|
10
10
|
|
11
|
+
module RubyProf
|
12
|
+
module DeprecationWarnings
|
13
|
+
def deprecation_warning(feature, recommendation = nil)
|
14
|
+
$stderr.puts "DEPRECATION WARNING: #{feature}"
|
15
|
+
$stderr.puts recommendation unless recommendation.nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
extend DeprecationWarnings
|
19
|
+
end
|
20
|
+
|
11
21
|
require 'ruby-prof/version'
|
12
22
|
require 'ruby-prof/call_info'
|
13
23
|
require 'ruby-prof/compatibility'
|
data/lib/ruby-prof/call_info.rb
CHANGED
@@ -9,17 +9,6 @@ module RubyProf
|
|
9
9
|
# children: array of call info children (can be empty)
|
10
10
|
# target: method info (containing an array of call infos)
|
11
11
|
|
12
|
-
attr_reader :recursive
|
13
|
-
|
14
|
-
def detect_recursion(visited_methods = Hash.new(0))
|
15
|
-
@recursive = (visited_methods[target] += 1) > 1
|
16
|
-
children.each do |child|
|
17
|
-
child.detect_recursion(visited_methods)
|
18
|
-
end
|
19
|
-
visited_methods.delete(target) if (visited_methods[target] -= 1) == 0
|
20
|
-
return @recursive
|
21
|
-
end
|
22
|
-
|
23
12
|
def children_time
|
24
13
|
children.inject(0) do |sum, call_info|
|
25
14
|
sum += call_info.total_time
|
@@ -18,10 +18,6 @@ module RubyProf
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def detect_recursion
|
22
|
-
call_infos.each(&:detect_recursion)
|
23
|
-
end
|
24
|
-
|
25
21
|
def called
|
26
22
|
@called ||= begin
|
27
23
|
call_infos.inject(0) do |sum, call_info|
|
@@ -33,7 +29,7 @@ module RubyProf
|
|
33
29
|
def total_time
|
34
30
|
@total_time ||= begin
|
35
31
|
call_infos.inject(0) do |sum, call_info|
|
36
|
-
sum += call_info.total_time
|
32
|
+
sum += call_info.total_time if !call_info.recursive?
|
37
33
|
sum
|
38
34
|
end
|
39
35
|
end
|
@@ -42,7 +38,7 @@ module RubyProf
|
|
42
38
|
def self_time
|
43
39
|
@self_time ||= begin
|
44
40
|
call_infos.inject(0) do |sum, call_info|
|
45
|
-
sum += call_info.self_time
|
41
|
+
sum += call_info.self_time if !call_info.recursive?
|
46
42
|
sum
|
47
43
|
end
|
48
44
|
end
|
@@ -51,7 +47,7 @@ module RubyProf
|
|
51
47
|
def wait_time
|
52
48
|
@wait_time ||= begin
|
53
49
|
call_infos.inject(0) do |sum, call_info|
|
54
|
-
sum += call_info.wait_time
|
50
|
+
sum += call_info.wait_time if !call_info.recursive?
|
55
51
|
sum
|
56
52
|
end
|
57
53
|
end
|
@@ -60,7 +56,7 @@ module RubyProf
|
|
60
56
|
def children_time
|
61
57
|
@children_time ||= begin
|
62
58
|
call_infos.inject(0) do |sum, call_info|
|
63
|
-
sum += call_info.children_time
|
59
|
+
sum += call_info.children_time if !call_info.recursive?
|
64
60
|
sum
|
65
61
|
end
|
66
62
|
end
|
@@ -78,10 +74,6 @@ module RubyProf
|
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
81
|
-
def recursive?
|
82
|
-
(@recursive ||= call_infos.detect(&:recursive) ? :true : :false) == :true
|
83
|
-
end
|
84
|
-
|
85
77
|
def children
|
86
78
|
@children ||= call_infos.map(&:children).flatten
|
87
79
|
end
|
@@ -26,6 +26,9 @@ module RubyProf
|
|
26
26
|
# Available values are :total_time, :self_time,
|
27
27
|
# :wait_time, :children_time
|
28
28
|
# Default value is :total_time
|
29
|
+
# :editor_uri - Specifies editor uri scheme used for opening files
|
30
|
+
# e.g. :atm or :mvim. For OS X default is :txmt.
|
31
|
+
# Use RUBY_PROF_EDITOR_URI environment variable to overide.
|
29
32
|
def setup_options(options = {})
|
30
33
|
@options = options
|
31
34
|
end
|
@@ -42,6 +45,16 @@ module RubyProf
|
|
42
45
|
@options[:sort_method] || :total_time
|
43
46
|
end
|
44
47
|
|
48
|
+
def editor_uri
|
49
|
+
default_uri = if RUBY_PLATFORM =~ /darwin/ \
|
50
|
+
&& !ENV['RUBY_PROF_EDITOR_URI']
|
51
|
+
'txmt'
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
55
|
+
ENV['RUBY_PROF_EDITOR_URI'] || @options[:editor_uri] || default_uri
|
56
|
+
end
|
57
|
+
|
45
58
|
def method_name(method)
|
46
59
|
name = method.full_name
|
47
60
|
if print_file
|
@@ -81,5 +94,10 @@ module RubyProf
|
|
81
94
|
|
82
95
|
def print_footer(thread)
|
83
96
|
end
|
97
|
+
|
98
|
+
# whether this printer need a :path option pointing to a directory
|
99
|
+
def self.needs_dir?
|
100
|
+
false
|
101
|
+
end
|
84
102
|
end
|
85
|
-
end
|
103
|
+
end
|
@@ -31,7 +31,7 @@ module RubyProf
|
|
31
31
|
@output << "wt:#{sprintf("%#{TIME_WIDTH}.2f", call_info.wait_time)}, "
|
32
32
|
@output << "ct:#{sprintf("%#{TIME_WIDTH}.2f", call_info.children_time)}, "
|
33
33
|
@output << "call:#{call_info.called}, "
|
34
|
-
@output << "rec:#{call_info.recursive}"
|
34
|
+
@output << "rec:#{call_info.recursive?}"
|
35
35
|
@output << ")"
|
36
36
|
@output << "\n"
|
37
37
|
end
|
@@ -36,9 +36,13 @@ module RubyProf
|
|
36
36
|
# :application - a String to overide the name of the application,
|
37
37
|
# as it appears on the report.
|
38
38
|
#
|
39
|
+
# :editor_uri - Specifies editor uri scheme used for opening files
|
40
|
+
# e.g. :atm or :mvim. For OS X default is :txmt.
|
41
|
+
# Use RUBY_PROF_EDITOR_URI environment variable to overide.
|
39
42
|
def print(output = STDOUT, options = {})
|
40
43
|
@output = output
|
41
44
|
setup_options(options)
|
45
|
+
@editor = editor_uri
|
42
46
|
if @graph_html = options.delete(:graph)
|
43
47
|
@graph_html = "file://" + @graph_html if @graph_html[0]=="/"
|
44
48
|
end
|
@@ -52,7 +56,7 @@ module RubyProf
|
|
52
56
|
@result.threads.each do |thread|
|
53
57
|
@current_thread_id = thread.fiber_id
|
54
58
|
@overall_time = thread.total_time
|
55
|
-
|
59
|
+
thread_info = String.new("Thread: #{thread.id}")
|
56
60
|
thread_info << ", Fiber: #{thread.fiber_id}" unless thread.id == thread.fiber_id
|
57
61
|
thread_info << " (#{"%4.2f%%" % ((@overall_time/@overall_threads_time)*100)} ~ #{@overall_time})"
|
58
62
|
@output.print "<div class=\"thread\">#{thread_info}</div>"
|
@@ -116,8 +120,10 @@ module RubyProf
|
|
116
120
|
if file =~ /\/ruby_runtime$/
|
117
121
|
h(name(call_info))
|
118
122
|
else
|
119
|
-
if
|
120
|
-
"<a href=\"
|
123
|
+
if @editor
|
124
|
+
"<a href=\"#{@editor}://" \
|
125
|
+
"open?url=file://#{file}&line=#{method.line}\">" \
|
126
|
+
"#{h(name(call_info))}</a>"
|
121
127
|
else
|
122
128
|
"<a href=\"file://#{file}##{method.line}\">#{h(name(call_info))}</a>"
|
123
129
|
end
|
@@ -257,4 +263,3 @@ end_help
|
|
257
263
|
end
|
258
264
|
end
|
259
265
|
end
|
260
|
-
|
@@ -44,11 +44,20 @@ module RubyProf
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def print(options = {})
|
47
|
+
validate_print_params(options)
|
47
48
|
setup_options(options)
|
48
49
|
determine_event_specification_and_value_scale
|
49
50
|
print_threads
|
50
51
|
end
|
51
52
|
|
53
|
+
def validate_print_params(options)
|
54
|
+
if options.is_a?(IO)
|
55
|
+
raise ArgumentError, "#{self.class.name}#print cannot print to IO objects"
|
56
|
+
elsif !options.is_a?(Hash)
|
57
|
+
raise ArgumentError, "#{self.class.name}#print requires an options hash"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
52
61
|
def print_threads
|
53
62
|
remove_subsidiary_files_from_previous_profile_runs
|
54
63
|
# TODO: merge fibers of a given thread here, instead of relying
|
@@ -79,6 +88,10 @@ module RubyProf
|
|
79
88
|
@options[:path] || "."
|
80
89
|
end
|
81
90
|
|
91
|
+
def self.needs_dir?
|
92
|
+
true
|
93
|
+
end
|
94
|
+
|
82
95
|
def base_name
|
83
96
|
@options[:profile] || "profile"
|
84
97
|
end
|
@@ -110,7 +123,7 @@ module RubyProf
|
|
110
123
|
def print_method(output, method)
|
111
124
|
# Print out the file and method name
|
112
125
|
output << "fl=#{file(method)}\n"
|
113
|
-
output << "fn=#{
|
126
|
+
output << "fn=#{method.calltree_name}\n"
|
114
127
|
|
115
128
|
# Now print out the function line number and its self time
|
116
129
|
output << "#{method.line} #{convert(method.self_time)}\n"
|
@@ -118,7 +131,7 @@ module RubyProf
|
|
118
131
|
# Now print out all the children methods
|
119
132
|
method.children.each do |callee|
|
120
133
|
output << "cfl=#{file(callee.target)}\n"
|
121
|
-
output << "cfn=#{
|
134
|
+
output << "cfn=#{callee.target.calltree_name}\n"
|
122
135
|
output << "calls=#{callee.called} #{callee.line}\n"
|
123
136
|
|
124
137
|
# Print out total times here!
|
@@ -13,6 +13,7 @@ module RubyProf
|
|
13
13
|
#
|
14
14
|
class FlatPrinterWithLineNumbers < FlatPrinter
|
15
15
|
def print_methods(thread)
|
16
|
+
@editor = editor_uri
|
16
17
|
total_time = thread.total_time
|
17
18
|
|
18
19
|
methods = thread.methods.sort_by(&sort_method).reverse
|
@@ -38,8 +39,8 @@ module RubyProf
|
|
38
39
|
if method.source_file == 'ruby_runtime'
|
39
40
|
@output << "\n"
|
40
41
|
else
|
41
|
-
@output << "\n
|
42
|
-
@output <<
|
42
|
+
@output << "\n defined at:\n"
|
43
|
+
@output << defined_at_format % [File.expand_path(method.source_file), method.line]
|
43
44
|
end
|
44
45
|
|
45
46
|
callers = []
|
@@ -52,13 +53,31 @@ module RubyProf
|
|
52
53
|
callers.uniq!
|
53
54
|
|
54
55
|
unless callers.empty?
|
55
|
-
@output << "
|
56
|
+
@output << " called from:\n"
|
56
57
|
callers.each do |args|
|
57
|
-
@output <<
|
58
|
+
@output << called_from_format % args
|
58
59
|
end
|
59
60
|
end
|
60
61
|
@output << "\n"
|
61
62
|
end
|
62
63
|
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def defined_at_format
|
68
|
+
if @editor
|
69
|
+
" #{@editor}://open?url=file://%s&line=%s\n"
|
70
|
+
else
|
71
|
+
" %s:%s\n"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def called_from_format
|
76
|
+
if @editor
|
77
|
+
" %s (#{@editor}://open?url=file://%s&line=%s)\n"
|
78
|
+
else
|
79
|
+
" %s (%s:%s)\n"
|
80
|
+
end
|
81
|
+
end
|
63
82
|
end
|
64
83
|
end
|
@@ -20,6 +20,9 @@ module RubyProf
|
|
20
20
|
# :template - specify an ERB template to use, instead of the
|
21
21
|
# built-in self.template
|
22
22
|
#
|
23
|
+
# :editor_uri - Specifies editor uri scheme used for opening files
|
24
|
+
# e.g. :atm or :mvim. For OS X default is :txmt.
|
25
|
+
# Use RUBY_PROF_EDITOR_URI environment variable to overide.
|
23
26
|
|
24
27
|
class GraphHtmlPrinter < AbstractPrinter
|
25
28
|
include ERB::Util
|
@@ -36,6 +39,7 @@ module RubyProf
|
|
36
39
|
def print(output = STDOUT, options = {})
|
37
40
|
@output = output
|
38
41
|
setup_options(options)
|
42
|
+
@editor = editor_uri
|
39
43
|
@output << @erb.result(binding).split("\n").map(&:rstrip).join("\n") << "\n"
|
40
44
|
end
|
41
45
|
|
@@ -63,8 +67,10 @@ module RubyProf
|
|
63
67
|
if srcfile =~ /\/ruby_runtime$/
|
64
68
|
""
|
65
69
|
else
|
66
|
-
if
|
67
|
-
"<a href=\"
|
70
|
+
if @editor
|
71
|
+
"<a href=\"#{@editor}://" \
|
72
|
+
"open?url=file://#{h srcfile}&line=#{linenum}\"" \
|
73
|
+
"title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
|
68
74
|
else
|
69
75
|
"<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
|
70
76
|
end
|
@@ -194,8 +200,8 @@ module RubyProf
|
|
194
200
|
</tr>
|
195
201
|
<% end %>
|
196
202
|
<tr class="method">
|
197
|
-
<td><%= sprintf("%.2f
|
198
|
-
<td><%= sprintf("%.2f
|
203
|
+
<td><%= sprintf("%.2f%%", total_percentage) %></td>
|
204
|
+
<td><%= sprintf("%.2f%%", self_percentage) %></td>
|
199
205
|
<td><%= sprintf("%.2f", method.total_time) %></td>
|
200
206
|
<td><%= sprintf("%.2f", method.self_time) %></td>
|
201
207
|
<td><%= sprintf("%.2f", method.wait_time) %></td>
|
@@ -241,4 +247,3 @@ module RubyProf
|
|
241
247
|
end
|
242
248
|
end
|
243
249
|
end
|
244
|
-
|
@@ -56,8 +56,8 @@ module RubyProf
|
|
56
56
|
print_parents(thread, method)
|
57
57
|
|
58
58
|
# 1 is for % sign
|
59
|
-
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f
|
60
|
-
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f
|
59
|
+
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", total_percentage)
|
60
|
+
@output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", self_percentage)
|
61
61
|
@output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
|
62
62
|
@output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
|
63
63
|
@output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
|
@@ -5,33 +5,30 @@ module RubyProf
|
|
5
5
|
# one profiling run. Currently prints a flat profile, a callgrind
|
6
6
|
# profile, a call stack profile and a graph profile.
|
7
7
|
class MultiPrinter
|
8
|
-
def initialize(result)
|
9
|
-
@stack_printer = CallStackPrinter.new(result)
|
10
|
-
@graph_printer = GraphHtmlPrinter.new(result)
|
11
|
-
@tree_printer = CallTreePrinter.new(result)
|
12
|
-
@flat_printer = FlatPrinter.new(result)
|
8
|
+
def initialize(result, printers = [:stack, :graph, :tree, :flat])
|
9
|
+
@stack_printer = CallStackPrinter.new(result) if printers.include?(:stack)
|
10
|
+
@graph_printer = GraphHtmlPrinter.new(result) if printers.include?(:graph)
|
11
|
+
@tree_printer = CallTreePrinter.new(result) if printers.include?(:tree)
|
12
|
+
@flat_printer = FlatPrinter.new(result) if printers.include?(:flat)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.needs_dir?
|
16
|
+
true
|
13
17
|
end
|
14
18
|
|
15
19
|
# create profile files under options[:path] or the current
|
16
20
|
# directory. options[:profile] is used as the base name for the
|
17
21
|
# pofile file, defaults to "profile".
|
18
22
|
def print(options)
|
23
|
+
validate_print_params(options)
|
24
|
+
|
19
25
|
@profile = options.delete(:profile) || "profile"
|
20
26
|
@directory = options.delete(:path) || File.expand_path(".")
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
File.open(graph_profile, "w") do |f|
|
27
|
-
@graph_printer.print(f, options)
|
28
|
-
end
|
29
|
-
|
30
|
-
@tree_printer.print(options.merge(:path => @directory, :profile => @profile))
|
31
|
-
|
32
|
-
File.open(flat_profile, "w") do |f|
|
33
|
-
@flat_printer.print(f, options)
|
34
|
-
end
|
28
|
+
print_to_stack(options) if @stack_printer
|
29
|
+
print_to_graph(options) if @graph_printer
|
30
|
+
print_to_tree(options) if @tree_printer
|
31
|
+
print_to_flat(options) if @flat_printer
|
35
32
|
end
|
36
33
|
|
37
34
|
# the name of the call stack profile file
|
@@ -54,5 +51,34 @@ module RubyProf
|
|
54
51
|
"#{@directory}/#{@profile}.flat.txt"
|
55
52
|
end
|
56
53
|
|
54
|
+
def print_to_stack(options)
|
55
|
+
File.open(stack_profile, "w") do |f|
|
56
|
+
@stack_printer.print(f, options.merge(:graph => "#{@profile}.graph.html"))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_to_graph(options)
|
61
|
+
File.open(graph_profile, "w") do |f|
|
62
|
+
@graph_printer.print(f, options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def print_to_tree(options)
|
67
|
+
@tree_printer.print(options.merge(:path => @directory, :profile => @profile))
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_to_flat(options)
|
71
|
+
File.open(flat_profile, "w") do |f|
|
72
|
+
@flat_printer.print(f, options)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate_print_params(options)
|
77
|
+
if options.is_a?(IO)
|
78
|
+
raise ArgumentError, "#{self.class.name}#print cannot print to IO objects"
|
79
|
+
elsif !options.is_a?(Hash)
|
80
|
+
raise ArgumentError, "#{self.class.name}#print requires an options hash"
|
81
|
+
end
|
82
|
+
end
|
57
83
|
end
|
58
84
|
end
|
data/lib/ruby-prof/profile.rb
CHANGED
@@ -1,55 +1,26 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'ruby-prof/profile/exclude_common_methods'
|
4
|
+
require 'ruby-prof/profile/legacy_method_elimination'
|
5
|
+
|
3
6
|
module RubyProf
|
4
7
|
class Profile
|
5
|
-
|
6
|
-
# but before results are returned to the user. Thus it provides
|
7
|
-
# a hook to do any necessary post-processing on the call graph.
|
8
|
-
def post_process
|
9
|
-
self.threads.each do |thread|
|
10
|
-
thread.detect_recursion
|
11
|
-
end
|
12
|
-
end
|
8
|
+
include LegacyMethodElimination
|
13
9
|
|
14
|
-
#
|
15
|
-
#
|
16
|
-
def
|
17
|
-
|
18
|
-
eliminated = []
|
19
|
-
threads.each do |thread|
|
20
|
-
matchers.each{ |matcher| eliminated.concat(eliminate_methods(thread.methods, matcher)) }
|
21
|
-
end
|
22
|
-
eliminated
|
10
|
+
# Hides methods that, when represented as a call graph, have
|
11
|
+
# extremely large in and out degrees and make navigation impossible.
|
12
|
+
def exclude_common_methods!
|
13
|
+
ExcludeCommonMethods.apply!(self)
|
23
14
|
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def read_regexps_from_file(file_name)
|
29
|
-
matchers = []
|
30
|
-
File.open(file_name).each_line do |l|
|
31
|
-
next if (l =~ /^(#.*|\s*)$/) # emtpy lines and lines starting with #
|
32
|
-
matchers << Regexp.new(l.strip)
|
16
|
+
def exclude_methods!(mod, *method_or_methods)
|
17
|
+
[method_or_methods].flatten.each do |name|
|
18
|
+
exclude_method!(mod, name)
|
33
19
|
end
|
34
20
|
end
|
35
21
|
|
36
|
-
|
37
|
-
|
38
|
-
eliminated = []
|
39
|
-
i = 0
|
40
|
-
while i < methods.size
|
41
|
-
method_info = methods[i]
|
42
|
-
method_name = method_info.full_name
|
43
|
-
if matcher === method_name
|
44
|
-
raise "can't eliminate root method" if method_info.root?
|
45
|
-
eliminated << methods.delete_at(i)
|
46
|
-
method_info.eliminate!
|
47
|
-
else
|
48
|
-
i += 1
|
49
|
-
end
|
50
|
-
end
|
51
|
-
eliminated
|
22
|
+
def exclude_singleton_methods!(mod, *method_or_methods)
|
23
|
+
exclude_methods!(mod.singleton_class, *method_or_methods)
|
52
24
|
end
|
53
|
-
|
54
25
|
end
|
55
26
|
end
|