ruby-prof 0.18.0-x64-mingw32 → 1.1.0-x64-mingw32

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +32 -0
  3. data/LICENSE +2 -2
  4. data/README.rdoc +1 -483
  5. data/Rakefile +3 -6
  6. data/bin/ruby-prof +65 -30
  7. data/ext/ruby_prof/extconf.rb +6 -38
  8. data/ext/ruby_prof/rp_allocation.c +279 -0
  9. data/ext/ruby_prof/rp_allocation.h +31 -0
  10. data/ext/ruby_prof/rp_call_info.c +129 -283
  11. data/ext/ruby_prof/rp_call_info.h +16 -34
  12. data/ext/ruby_prof/rp_measure_allocations.c +25 -49
  13. data/ext/ruby_prof/rp_measure_memory.c +21 -56
  14. data/ext/ruby_prof/rp_measure_process_time.c +35 -39
  15. data/ext/ruby_prof/rp_measure_wall_time.c +36 -19
  16. data/ext/ruby_prof/rp_measurement.c +230 -0
  17. data/ext/ruby_prof/rp_measurement.h +50 -0
  18. data/ext/ruby_prof/rp_method.c +389 -389
  19. data/ext/ruby_prof/rp_method.h +34 -39
  20. data/ext/ruby_prof/rp_profile.c +895 -0
  21. data/ext/ruby_prof/rp_profile.h +37 -0
  22. data/ext/ruby_prof/rp_stack.c +103 -80
  23. data/ext/ruby_prof/rp_stack.h +5 -12
  24. data/ext/ruby_prof/rp_thread.c +143 -83
  25. data/ext/ruby_prof/rp_thread.h +15 -6
  26. data/ext/ruby_prof/ruby_prof.c +11 -757
  27. data/ext/ruby_prof/ruby_prof.h +4 -47
  28. data/ext/ruby_prof/vc/ruby_prof.vcxproj +10 -8
  29. data/lib/{2.6.3 → 2.6.5}/ruby_prof.so +0 -0
  30. data/lib/ruby-prof.rb +2 -18
  31. data/lib/ruby-prof/assets/call_stack_printer.html.erb +713 -0
  32. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  33. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  34. data/lib/ruby-prof/call_info.rb +35 -93
  35. data/lib/ruby-prof/call_info_visitor.rb +19 -21
  36. data/lib/ruby-prof/compatibility.rb +37 -107
  37. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  38. data/lib/ruby-prof/measurement.rb +14 -0
  39. data/lib/ruby-prof/method_info.rb +52 -83
  40. data/lib/ruby-prof/printers/abstract_printer.rb +73 -50
  41. data/lib/ruby-prof/printers/call_info_printer.rb +13 -3
  42. data/lib/ruby-prof/printers/call_stack_printer.rb +62 -145
  43. data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
  44. data/lib/ruby-prof/printers/dot_printer.rb +5 -5
  45. data/lib/ruby-prof/printers/flat_printer.rb +6 -24
  46. data/lib/ruby-prof/printers/graph_html_printer.rb +6 -192
  47. data/lib/ruby-prof/printers/graph_printer.rb +13 -15
  48. data/lib/ruby-prof/printers/multi_printer.rb +66 -23
  49. data/lib/ruby-prof/profile.rb +10 -3
  50. data/lib/ruby-prof/rack.rb +0 -3
  51. data/lib/ruby-prof/thread.rb +12 -12
  52. data/lib/ruby-prof/version.rb +1 -1
  53. data/ruby-prof.gemspec +2 -2
  54. data/test/abstract_printer_test.rb +0 -27
  55. data/test/alias_test.rb +129 -0
  56. data/test/basic_test.rb +41 -40
  57. data/test/call_info_visitor_test.rb +3 -3
  58. data/test/dynamic_method_test.rb +0 -2
  59. data/test/fiber_test.rb +11 -17
  60. data/test/gc_test.rb +96 -0
  61. data/test/line_number_test.rb +120 -39
  62. data/test/marshal_test.rb +119 -0
  63. data/test/measure_allocations.rb +30 -0
  64. data/test/measure_allocations_test.rb +371 -12
  65. data/test/measure_allocations_trace_test.rb +385 -0
  66. data/test/measure_memory_trace_test.rb +756 -0
  67. data/test/measure_process_time_test.rb +821 -33
  68. data/test/measure_times.rb +54 -0
  69. data/test/measure_wall_time_test.rb +349 -145
  70. data/test/multi_printer_test.rb +1 -34
  71. data/test/parser_timings.rb +24 -0
  72. data/test/pause_resume_test.rb +5 -5
  73. data/test/prime.rb +2 -0
  74. data/test/printer_call_stack_test.rb +28 -0
  75. data/test/printer_call_tree_test.rb +31 -0
  76. data/test/printer_flat_test.rb +68 -0
  77. data/test/printer_graph_html_test.rb +60 -0
  78. data/test/printer_graph_test.rb +41 -0
  79. data/test/printers_test.rb +32 -166
  80. data/test/printing_recursive_graph_test.rb +26 -72
  81. data/test/recursive_test.rb +72 -77
  82. data/test/stack_printer_test.rb +2 -15
  83. data/test/start_stop_test.rb +22 -25
  84. data/test/test_helper.rb +5 -248
  85. data/test/thread_test.rb +11 -54
  86. data/test/unique_call_path_test.rb +16 -28
  87. data/test/yarv_test.rb +1 -0
  88. metadata +28 -36
  89. data/examples/flat.txt +0 -50
  90. data/examples/graph.dot +0 -84
  91. data/examples/graph.html +0 -823
  92. data/examples/graph.txt +0 -139
  93. data/examples/multi.flat.txt +0 -23
  94. data/examples/multi.graph.html +0 -760
  95. data/examples/multi.grind.dat +0 -114
  96. data/examples/multi.stack.html +0 -547
  97. data/examples/stack.html +0 -547
  98. data/ext/ruby_prof/rp_measure.c +0 -40
  99. data/ext/ruby_prof/rp_measure.h +0 -45
  100. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  101. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  102. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  103. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  104. data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
  105. data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
  106. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
  107. data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
  108. data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
  109. data/test/aggregate_test.rb +0 -136
  110. data/test/block_test.rb +0 -74
  111. data/test/call_info_test.rb +0 -78
  112. data/test/issue137_test.rb +0 -63
  113. data/test/measure_cpu_time_test.rb +0 -212
  114. data/test/measure_gc_runs_test.rb +0 -32
  115. data/test/measure_gc_time_test.rb +0 -36
  116. data/test/measure_memory_test.rb +0 -33
  117. data/test/method_elimination_test.rb +0 -84
  118. data/test/module_test.rb +0 -45
  119. data/test/stack_test.rb +0 -138
data/test/test_helper.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "rubygems"
4
4
  gem "minitest"
5
+ require 'singleton'
5
6
 
6
7
  # To make testing/debugging easier, test within this source tree versus an installed gem
7
8
  dir = File.dirname(__FILE__)
@@ -14,254 +15,10 @@ $LOAD_PATH << ext
14
15
 
15
16
  require 'ruby-prof'
16
17
 
17
- # stub deprecation warnings
18
- module RubyProf
19
- module SuppressDeprecationWarnings
20
- def deprecation_warning(*args)
21
- super if ENV['SHOW_RUBY_PROF_DEPRECATION_WARNINGS'] == '1'
22
- end
23
- end
24
- extend SuppressDeprecationWarnings
25
- end
26
-
18
+ # Disable minitest parallel tests. The problem is the thread switching will cahnge test results
19
+ # (self vs wait time)
20
+ ENV["N"] = "0"
27
21
  require 'minitest/autorun'
28
22
 
29
23
  class TestCase < Minitest::Test
30
- # I know this sucks, but ...
31
- def assert_nothing_raised(*)
32
- yield
33
- end
34
-
35
- def before_setup
36
- # make sure to exclude all threads except the one running the test
37
- # minitest allocates a thread pool and they would otherwise show
38
- # up in the profile data, breaking tests randomly
39
- RubyProf.exclude_threads = Thread.list.select{|t| t != Thread.current}
40
- end
41
-
42
- def after_teardown
43
- # reset exclude threads after testing
44
- RubyProf.exclude_threads = nil
45
- end
46
- end
47
-
48
- require File.expand_path('../prime', __FILE__)
49
-
50
- # Some classes used in measurement tests
51
- module RubyProf
52
- class C1
53
- def C1.hello
54
- sleep(0.1)
55
- end
56
-
57
- def hello
58
- sleep(0.2)
59
- end
60
- end
61
-
62
- module M1
63
- def hello
64
- sleep(0.3)
65
- end
66
- end
67
-
68
- class C2
69
- include M1
70
- extend M1
71
- end
72
-
73
- class C3
74
- def hello
75
- sleep(0.4)
76
- end
77
- end
78
-
79
- module M4
80
- def hello
81
- sleep(0.5)
82
- end
83
- end
84
-
85
- module M5
86
- include M4
87
- def goodbye
88
- hello
89
- end
90
- end
91
-
92
- class C6
93
- include M5
94
- def test
95
- goodbye
96
- end
97
- end
98
-
99
- class C7
100
- def self.busy_wait
101
- t = Time.now.to_f
102
- while Time.now.to_f - t < 0.1; end
103
- end
104
-
105
- def self.sleep_wait
106
- sleep 0.1
107
- end
108
-
109
- def busy_wait
110
- t = Time.now.to_f
111
- while Time.now.to_f - t < 0.2; end
112
- end
113
-
114
- def sleep_wait
115
- sleep 0.2
116
- end
117
- end
118
-
119
- module M7
120
- def busy_wait
121
- t = Time.now.to_f
122
- while Time.now.to_f - t < 0.3; end
123
- end
124
-
125
- def sleep_wait
126
- sleep 0.3
127
- end
128
- end
129
-
130
- class C8
131
- include M7
132
- extend M7
133
- end
134
-
135
- def self.ruby_major_version
136
- match = RUBY_VERSION.match(/(\d)\.(\d)/)
137
- return Integer(match[1])
138
- end
139
-
140
- def self.ruby_minor_version
141
- match = RUBY_VERSION.match(/(\d)\.(\d)/)
142
- return Integer(match[2])
143
- end
144
-
145
- def self.parent_object
146
- if ruby_major_version == 1 && ruby_minor_version == 8
147
- Object
148
- else
149
- BasicObject
150
- end
151
- end
152
-
153
- def self.ruby_2?
154
- ruby_major_version == 2
155
- end
156
-
157
- # store printer output in this directory
158
- def self.tmpdir
159
- path = File.expand_path('../../tmp', __FILE__)
160
- unless Dir.exist?(path)
161
- Dir.mkdir(path)
162
- end
163
- path
164
- end
165
- end
166
-
167
- module MemoryTestHelper
168
- def memory_test_helper
169
- result = RubyProf.profile {Array.new}
170
- total = result.threads.first.methods.inject(0) { |sum, m| sum + m.total_time }
171
- assert(total < 1_000_000, 'Total should not have subtract overflow error')
172
- total
173
- end
174
- end
175
-
176
- module PrinterTestHelper
177
- Metrics = Struct.new(:name, :total, :self_t, :wait, :child, :calls)
178
- class Metrics
179
- def pp
180
- "%s[total: %.2f, self: %.2f, wait: %.2f, child: %.2f, calls: %s]" %
181
- [name, total, self_t, wait, child, calls]
182
- end
183
- end
184
-
185
- Entry = Struct.new(:total_p, :self_p, :metrics, :parents, :children)
186
- class Entry
187
- def child(name)
188
- children.detect{|m| m.name == name}
189
- end
190
-
191
- def parent(name)
192
- parents.detect{|m| m.name == name}
193
- end
194
-
195
- def pp
196
- res = ""
197
- res << "NODE (total%%: %.2f, self%%: %.2f) %s\n" % [total_p, self_p, metrics.pp]
198
- res << " PARENTS:\n"
199
- parents.each {|m| res << " " + m.pp << "\n"}
200
- res << " CHILDREN:\n"
201
- children.each {|m| res << " " + m.pp << "\n"}
202
- res
203
- end
204
- end
205
-
206
- class MetricsArray < Array
207
- def metrics_for(name)
208
- detect {|e| e.metrics.name == name}
209
- end
210
-
211
- def pp(io = STDOUT)
212
- entries = map do |e|
213
- begin
214
- e.pp
215
- rescue
216
- puts $!.message + e.inspect
217
- ""
218
- end
219
- end
220
- io.puts entries.join("--------------------------------------------------\n")
221
- end
222
-
223
- def self.parse(str)
224
- res = new
225
- entry = nil
226
- relatives = []
227
- state = :preamble
228
-
229
- str.each_line do |l|
230
- line = l.chomp.strip
231
- if line =~ /-----/
232
- if state == :preamble
233
- state = :parsing_parents
234
- entry = Entry.new
235
- elsif state == :parsing_parents
236
- entry = Entry.new
237
- elsif state == :parsing_children
238
- entry.children = relatives
239
- res << entry
240
- entry = Entry.new
241
- relatives = []
242
- state = :parsing_parents
243
- end
244
- elsif line =~ /^\s*$/ || line =~ /indicates recursively called methods/
245
- next
246
- elsif state != :preamble
247
- elements = line.split(/\s+/)
248
- method = elements.pop
249
- numbers = elements[0..-2].map(&:to_f)
250
- metrics = Metrics.new(method, *numbers[-4..-1], elements[-1])
251
- if numbers.size == 6
252
- entry.metrics = metrics
253
- entry.total_p = numbers[0]
254
- entry.self_p = numbers[1]
255
- entry.parents = relatives
256
- entry.children = relatives = []
257
- state = :parsing_children
258
- res << entry
259
- else
260
- relatives << metrics
261
- end
262
- end
263
- end
264
- res
265
- end
266
- end
267
- end
24
+ end
data/test/thread_test.rb CHANGED
@@ -75,10 +75,7 @@ class ThreadTest < TestCase
75
75
  assert_in_delta(0, method.self_time, 0.05)
76
76
  assert_in_delta(0, method.wait_time, 0.05)
77
77
  assert_in_delta(1, method.children_time, 0.05)
78
- assert_equal(1, method.call_infos.length)
79
- call_info = method.call_infos[0]
80
- assert_equal('ThreadTest#test_thread_timings', call_info.call_sequence)
81
- assert_equal(1, call_info.children.length)
78
+ assert_equal(1, method.callers.length)
82
79
 
83
80
  method = methods[1]
84
81
  assert_equal('Kernel#sleep', method.full_name)
@@ -88,10 +85,8 @@ class ThreadTest < TestCase
88
85
  assert_in_delta(0, method.wait_time, 0.05)
89
86
  assert_in_delta(0, method.children_time, 0.05)
90
87
 
91
- assert_equal(1, method.call_infos.length)
92
- call_info = method.call_infos[0]
93
- assert_equal('ThreadTest#test_thread_timings->Kernel#sleep', call_info.call_sequence)
94
- assert_equal(0, call_info.children.length)
88
+ assert_equal(1, method.callers.length)
89
+ assert_equal(0, method.callees.length)
95
90
 
96
91
  # Check foreground thread
97
92
  rp_thread = result.threads.detect {|athread| athread.id == Thread.current.object_id}
@@ -110,10 +105,8 @@ class ThreadTest < TestCase
110
105
  assert_in_delta(0, method.wait_time, 0.05)
111
106
  assert_in_delta(1, method.children_time, 0.05)
112
107
 
113
- assert_equal(1, method.call_infos.length)
114
- call_info = method.call_infos[0]
115
- assert_equal('ThreadTest#test_thread_timings', call_info.call_sequence)
116
- assert_equal(2, call_info.children.length)
108
+ assert_equal(1, method.callers.length)
109
+ assert_equal(2, method.callees.length)
117
110
 
118
111
  method = methods[1]
119
112
  assert_equal('Thread#join', method.full_name)
@@ -123,10 +116,8 @@ class ThreadTest < TestCase
123
116
  assert_in_delta(1.0, method.wait_time, 0.05)
124
117
  assert_in_delta(0, method.children_time, 0.05)
125
118
 
126
- assert_equal(1, method.call_infos.length)
127
- call_info = method.call_infos[0]
128
- assert_equal('ThreadTest#test_thread_timings->Thread#join', call_info.call_sequence)
129
- assert_equal(0, call_info.children.length)
119
+ assert_equal(1, method.callers.length)
120
+ assert_equal(0, method.callees.length)
130
121
 
131
122
  method = methods[2]
132
123
  assert_equal('<Class::Thread>#new', method.full_name)
@@ -136,10 +127,8 @@ class ThreadTest < TestCase
136
127
  assert_in_delta(0, method.wait_time, 0.05)
137
128
  assert_in_delta(0, method.children_time, 0.05)
138
129
 
139
- assert_equal(1, method.call_infos.length)
140
- call_info = method.call_infos[0]
141
- assert_equal('ThreadTest#test_thread_timings-><Class::Thread>#new', call_info.call_sequence)
142
- assert_equal(1, call_info.children.length)
130
+ assert_equal(1, method.callers.length)
131
+ assert_equal(1, method.callees.length)
143
132
 
144
133
  method = methods[3]
145
134
  assert_equal('Thread#initialize', method.full_name)
@@ -149,39 +138,7 @@ class ThreadTest < TestCase
149
138
  assert_in_delta(0, method.wait_time, 0.05)
150
139
  assert_in_delta(0, method.children_time, 0.05)
151
140
 
152
- assert_equal(1, method.call_infos.length)
153
- call_info = method.call_infos[0]
154
- assert_equal('ThreadTest#test_thread_timings-><Class::Thread>#new->Thread#initialize', call_info.call_sequence)
155
- assert_equal(0, call_info.children.length)
156
- end
157
-
158
- # useless test: what does it test?
159
- def test_thread_back_and_forth
160
- result = nil
161
- seconds = Benchmark.realtime do
162
- result = RubyProf.profile do
163
- a = Thread.new { 100_000.times { sleep 0 }}
164
- b = Thread.new { 100_000.times { sleep 0 }}
165
- a.join
166
- b.join
167
- end
168
- end
169
- methods = result.threads.map {|thread| thread.methods}
170
- timings = methods.flatten.sort
171
- assert(timings[-1].total_time < seconds)
172
- end
173
-
174
- # useless test: what does it test?
175
- def test_thread
176
- RubyProf.profile do
177
- begin
178
- Timeout::timeout(2) do
179
- while true
180
- next
181
- end
182
- end
183
- rescue Timeout::Error
184
- end
185
- end
141
+ assert_equal(1, method.callers.length)
142
+ assert_equal(0, method.callees.length)
186
143
  end
187
144
  end
@@ -67,8 +67,8 @@ class UniqueCallPathTest < TestCase
67
67
  assert_equal(1, root_methods.length)
68
68
 
69
69
  root_children = Array.new
70
- root_methods[0].children.each do | c |
71
- if c.parent.target.eql?(root_methods[0])
70
+ root_methods[0].callees.each do | c |
71
+ if c.parent.eql?(root_methods[0])
72
72
  root_children.push(c)
73
73
  end
74
74
  end
@@ -103,32 +103,26 @@ class UniqueCallPathTest < TestCase
103
103
  method = root_methods[0]
104
104
  assert_equal('UniqueCallPathTest#test_children_of', method.full_name)
105
105
 
106
- call_info_a = nil
107
- root_methods[0].children.each do | c |
108
- if c.target.full_name == "UniqueCallPath#method_a"
109
- call_info_a = c
110
- break
111
- end
106
+ call_info_a = root_methods[0].callees.detect do |call_info|
107
+ call_info.target.full_name == "UniqueCallPath#method_a"
112
108
  end
113
-
114
- assert !call_info_a.nil?
109
+ refute_nil(call_info_a)
115
110
 
116
111
  children_of_a = Array.new
117
112
 
118
- call_info_a.children.each do | c |
113
+ call_info_a.target.callees.each do | c |
119
114
  if c.parent.eql?(call_info_a)
120
115
  children_of_a.push(c)
121
116
  end
122
117
  end
123
118
 
124
- assert_equal(2, call_info_a.target.children.length)
119
+ assert_equal(2, call_info_a.target.callees.length)
125
120
 
126
121
  children_of_a = children_of_a.sort do |c1, c2|
127
122
  c1.target.full_name <=> c2.target.full_name
128
123
  end
129
124
 
130
- assert_equal(1, children_of_a.length)
131
- assert_equal("UniqueCallPath#method_b", children_of_a[0].target.full_name)
125
+ assert_equal(0, children_of_a.length)
132
126
  end
133
127
 
134
128
  def test_id2ref
@@ -147,8 +141,7 @@ class UniqueCallPathTest < TestCase
147
141
  end
148
142
  end
149
143
 
150
- child = root_methods[0].children[0]
151
-
144
+ child = root_methods[0].callees[0]
152
145
  refute_equal(0, child.object_id)
153
146
  #assert_equal(RubyProf::CallInfo.id2ref(child.id).target.full_name, child.target.full_name)
154
147
  end
@@ -172,31 +165,26 @@ class UniqueCallPathTest < TestCase
172
165
 
173
166
  assert_equal(1, root_methods.length)
174
167
 
175
- call_info_a = nil
176
- root_methods[0].children.each do | c |
177
- if c.target.full_name == "UniqueCallPath#method_a"
178
- call_info_a = c
179
- break
180
- end
168
+ call_info_a = root_methods[0].callees.detect do |call_info|
169
+ call_info.target.full_name == "UniqueCallPath#method_a"
181
170
  end
182
-
183
- assert !call_info_a.nil?
171
+ refute_nil(call_info_a)
184
172
 
185
173
  children_of_a = Array.new
186
- call_info_a.children.each do |c|
187
- if c.parent.eql?(call_info_a)
174
+ call_info_a.target.callees.each do |c|
175
+ if c.parent.eql?(call_info_a.target)
188
176
  children_of_a.push(c)
189
177
  end
190
178
  end
191
179
 
192
- assert_equal(2, call_info_a.target.children.length)
180
+ assert_equal(1, call_info_a.target.callees.length)
193
181
 
194
182
  children_of_a = children_of_a.sort do |c1, c2|
195
183
  c1.target.full_name <=> c2.target.full_name
196
184
  end
197
185
 
198
186
  assert_equal(1, children_of_a.length)
199
- assert_equal(1, children_of_a[0].called)
187
+ assert_equal(2, children_of_a[0].called)
200
188
  assert_equal("UniqueCallPath#method_b", children_of_a[0].target.full_name)
201
189
  end
202
190
  end