ruby-prof 1.4.3 → 1.6.3

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +59 -9
  3. data/{README.rdoc → README.md} +2 -2
  4. data/Rakefile +4 -4
  5. data/bin/ruby-prof +100 -87
  6. data/ext/ruby_prof/rp_allocation.c +140 -85
  7. data/ext/ruby_prof/rp_allocation.h +8 -6
  8. data/ext/ruby_prof/rp_call_tree.c +502 -369
  9. data/ext/ruby_prof/rp_call_tree.h +47 -43
  10. data/ext/ruby_prof/rp_call_trees.c +16 -8
  11. data/ext/ruby_prof/rp_measure_allocations.c +10 -13
  12. data/ext/ruby_prof/rp_measure_memory.c +8 -4
  13. data/ext/ruby_prof/rp_measure_process_time.c +7 -6
  14. data/ext/ruby_prof/rp_measurement.c +147 -20
  15. data/ext/ruby_prof/rp_measurement.h +4 -1
  16. data/ext/ruby_prof/rp_method.c +142 -83
  17. data/ext/ruby_prof/rp_method.h +63 -62
  18. data/ext/ruby_prof/rp_profile.c +933 -900
  19. data/ext/ruby_prof/rp_profile.h +1 -0
  20. data/ext/ruby_prof/rp_thread.c +433 -362
  21. data/ext/ruby_prof/rp_thread.h +39 -39
  22. data/ext/ruby_prof/ruby_prof.c +0 -2
  23. data/ext/ruby_prof/ruby_prof.h +8 -0
  24. data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -8
  25. data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
  26. data/lib/ruby-prof/compatibility.rb +14 -0
  27. data/lib/ruby-prof/method_info.rb +8 -1
  28. data/lib/ruby-prof/printers/abstract_printer.rb +2 -1
  29. data/lib/ruby-prof/printers/call_tree_printer.rb +4 -10
  30. data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
  31. data/lib/ruby-prof/printers/multi_printer.rb +17 -17
  32. data/lib/ruby-prof/profile.rb +70 -37
  33. data/lib/ruby-prof/rack.rb +31 -21
  34. data/lib/ruby-prof/version.rb +1 -1
  35. data/lib/ruby-prof.rb +1 -1
  36. data/ruby-prof.gemspec +2 -3
  37. data/test/abstract_printer_test.rb +1 -0
  38. data/test/alias_test.rb +97 -106
  39. data/test/call_tree_builder.rb +126 -0
  40. data/test/call_tree_test.rb +94 -0
  41. data/test/call_tree_visitor_test.rb +1 -6
  42. data/test/call_trees_test.rb +6 -6
  43. data/test/{basic_test.rb → compatibility_test.rb} +8 -2
  44. data/test/duplicate_names_test.rb +5 -5
  45. data/test/dynamic_method_test.rb +24 -15
  46. data/test/enumerable_test.rb +1 -1
  47. data/test/exceptions_test.rb +2 -2
  48. data/test/exclude_methods_test.rb +3 -8
  49. data/test/exclude_threads_test.rb +4 -9
  50. data/test/fiber_test.rb +74 -8
  51. data/test/gc_test.rb +11 -9
  52. data/test/inverse_call_tree_test.rb +33 -34
  53. data/test/line_number_test.rb +37 -61
  54. data/test/marshal_test.rb +16 -3
  55. data/test/measure_allocations.rb +1 -5
  56. data/test/measure_allocations_test.rb +642 -357
  57. data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +180 -616
  58. data/test/measure_process_time_test.rb +1566 -741
  59. data/test/measure_wall_time_test.rb +179 -193
  60. data/test/measurement_test.rb +82 -0
  61. data/test/merge_test.rb +146 -0
  62. data/test/method_info_test.rb +95 -0
  63. data/test/multi_printer_test.rb +0 -5
  64. data/test/no_method_class_test.rb +1 -1
  65. data/test/pause_resume_test.rb +12 -16
  66. data/test/printer_call_stack_test.rb +2 -2
  67. data/test/printer_call_tree_test.rb +4 -4
  68. data/test/printer_flat_test.rb +1 -1
  69. data/test/printer_graph_html_test.rb +2 -2
  70. data/test/printer_graph_test.rb +2 -2
  71. data/test/printers_test.rb +14 -20
  72. data/test/printing_recursive_graph_test.rb +2 -2
  73. data/test/profile_test.rb +85 -0
  74. data/test/recursive_test.rb +374 -155
  75. data/test/scheduler.rb +363 -0
  76. data/test/singleton_test.rb +1 -1
  77. data/test/stack_printer_test.rb +5 -8
  78. data/test/start_stop_test.rb +11 -14
  79. data/test/test_helper.rb +11 -8
  80. data/test/thread_test.rb +106 -15
  81. data/test/unique_call_path_test.rb +28 -12
  82. data/test/yarv_test.rb +11 -7
  83. metadata +17 -29
  84. data/ext/ruby_prof/rp_aggregate_call_tree.c +0 -59
  85. data/ext/ruby_prof/rp_aggregate_call_tree.h +0 -13
  86. data/test/measure_allocations_trace_test.rb +0 -375
  87. data/test/temp.rb +0 -20
data/test/scheduler.rb ADDED
@@ -0,0 +1,363 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an example and simplified scheduler for test purposes.
4
+ # It is not efficient for a large number of file descriptors as it uses IO.select().
5
+ # Production Fiber schedulers should use epoll/kqueue/etc.
6
+
7
+ require 'fiber'
8
+ require 'socket'
9
+
10
+ begin
11
+ require 'io/nonblock'
12
+ rescue LoadError
13
+ # Ignore.
14
+ end
15
+
16
+ class Scheduler
17
+ experimental = Warning[:experimental]
18
+ begin
19
+ Warning[:experimental] = false
20
+ IO::Buffer.new(0)
21
+ ensure
22
+ Warning[:experimental] = experimental
23
+ end
24
+
25
+ def initialize
26
+ @readable = {}
27
+ @writable = {}
28
+ @waiting = {}
29
+
30
+ @closed = false
31
+
32
+ @lock = Thread::Mutex.new
33
+ @blocking = Hash.new.compare_by_identity
34
+ @ready = []
35
+
36
+ @urgent = IO.pipe
37
+ end
38
+
39
+ attr :readable
40
+ attr :writable
41
+ attr :waiting
42
+
43
+ def next_timeout
44
+ _fiber, timeout = @waiting.min_by{|key, value| value}
45
+
46
+ if timeout
47
+ offset = timeout - current_time
48
+
49
+ if offset < 0
50
+ return 0
51
+ else
52
+ return offset
53
+ end
54
+ end
55
+ end
56
+
57
+ def run
58
+ # $stderr.puts [__method__, Fiber.current].inspect
59
+
60
+ while @readable.any? or @writable.any? or @waiting.any? or @blocking.any?
61
+ # Can only handle file descriptors up to 1024...
62
+ readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout)
63
+
64
+ # puts "readable: #{readable}" if readable&.any?
65
+ # puts "writable: #{writable}" if writable&.any?
66
+
67
+ selected = {}
68
+
69
+ readable&.each do |io|
70
+ if fiber = @readable.delete(io)
71
+ @writable.delete(io) if @writable[io] == fiber
72
+ selected[fiber] = IO::READABLE
73
+ elsif io == @urgent.first
74
+ @urgent.first.read_nonblock(1024)
75
+ end
76
+ end
77
+
78
+ writable&.each do |io|
79
+ if fiber = @writable.delete(io)
80
+ @readable.delete(io) if @readable[io] == fiber
81
+ selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE
82
+ end
83
+ end
84
+
85
+ selected.each do |fiber, events|
86
+ fiber.resume(events)
87
+ end
88
+
89
+ if @waiting.any?
90
+ time = current_time
91
+ waiting, @waiting = @waiting, {}
92
+
93
+ waiting.each do |fiber, timeout|
94
+ if fiber.alive?
95
+ if timeout <= time
96
+ fiber.resume
97
+ else
98
+ @waiting[fiber] = timeout
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ if @ready.any?
105
+ ready = nil
106
+
107
+ @lock.synchronize do
108
+ ready, @ready = @ready, []
109
+ end
110
+
111
+ ready.each do |fiber|
112
+ fiber.resume
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ def scheduler_close
119
+ close(true)
120
+ end
121
+
122
+ def close(internal = false)
123
+ # $stderr.puts [__method__, Fiber.current].inspect
124
+
125
+ unless internal
126
+ if Fiber.scheduler == self
127
+ return Fiber.set_scheduler(nil)
128
+ end
129
+ end
130
+
131
+ if @closed
132
+ raise "Scheduler already closed!"
133
+ end
134
+
135
+ self.run
136
+ ensure
137
+ if @urgent
138
+ @urgent.each(&:close)
139
+ @urgent = nil
140
+ end
141
+
142
+ @closed ||= true
143
+
144
+ # We freeze to detect any unintended modifications after the scheduler is closed:
145
+ self.freeze
146
+ end
147
+
148
+ def closed?
149
+ @closed
150
+ end
151
+
152
+ def current_time
153
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
154
+ end
155
+
156
+ def timeout_after(duration, klass, message, &block)
157
+ fiber = Fiber.current
158
+
159
+ self.fiber do
160
+ sleep(duration)
161
+
162
+ if fiber&.alive?
163
+ fiber.raise(klass, message)
164
+ end
165
+ end
166
+
167
+ begin
168
+ yield(duration)
169
+ ensure
170
+ fiber = nil
171
+ end
172
+ end
173
+
174
+ def process_wait(pid, flags)
175
+ # $stderr.puts [__method__, pid, flags, Fiber.current].inspect
176
+
177
+ # This is a very simple way to implement a non-blocking wait:
178
+ Thread.new do
179
+ Process::Status.wait(pid, flags)
180
+ end.value
181
+ end
182
+
183
+ def io_wait(io, events, duration)
184
+ # $stderr.puts [__method__, io, events, duration, Fiber.current].inspect
185
+
186
+ unless (events & IO::READABLE).zero?
187
+ @readable[io] = Fiber.current
188
+ end
189
+
190
+ unless (events & IO::WRITABLE).zero?
191
+ @writable[io] = Fiber.current
192
+ end
193
+
194
+ Fiber.yield
195
+ ensure
196
+ @readable.delete(io)
197
+ @writable.delete(io)
198
+ end
199
+
200
+ def io_select(...)
201
+ # Emulate the operation using a non-blocking thread:
202
+ Thread.new do
203
+ IO.select(...)
204
+ end.value
205
+ end
206
+
207
+ # Used for Kernel#sleep and Thread::Mutex#sleep
208
+ def kernel_sleep(duration = nil)
209
+ # $stderr.puts [__method__, duration, Fiber.current].inspect
210
+
211
+ self.block(:sleep, duration)
212
+
213
+ return true
214
+ end
215
+
216
+ # Used when blocking on synchronization (Thread::Mutex#lock,
217
+ # Thread::Queue#pop, Thread::SizedQueue#push, ...)
218
+ def block(blocker, timeout = nil)
219
+ # $stderr.puts [__method__, blocker, timeout].inspect
220
+
221
+ fiber = Fiber.current
222
+
223
+ if timeout
224
+ @waiting[fiber] = current_time + timeout
225
+ begin
226
+ Fiber.yield
227
+ ensure
228
+ # Remove from @waiting in the case #unblock was called before the timeout expired:
229
+ @waiting.delete(fiber)
230
+ end
231
+ else
232
+ @blocking[fiber] = true
233
+ begin
234
+ Fiber.yield
235
+ ensure
236
+ @blocking.delete(fiber)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Used when synchronization wakes up a previously-blocked fiber
242
+ # (Thread::Mutex#unlock, Thread::Queue#push, ...).
243
+ # This might be called from another thread.
244
+ def unblock(blocker, fiber)
245
+ # $stderr.puts [__method__, blocker, fiber].inspect
246
+ # $stderr.puts blocker.backtrace.inspect
247
+ # $stderr.puts fiber.backtrace.inspect
248
+
249
+ @lock.synchronize do
250
+ @ready << fiber
251
+ end
252
+
253
+ io = @urgent.last
254
+ io.write_nonblock('.')
255
+ end
256
+
257
+ def fiber(&block)
258
+ fiber = Fiber.new(blocking: false, &block)
259
+
260
+ fiber.resume
261
+
262
+ return fiber
263
+ end
264
+
265
+ def address_resolve(hostname)
266
+ Thread.new do
267
+ Addrinfo.getaddrinfo(hostname, nil).map(&:ip_address).uniq
268
+ end.value
269
+ end
270
+ end
271
+
272
+ class IOBufferScheduler < Scheduler
273
+ EAGAIN = -Errno::EAGAIN::Errno
274
+
275
+ def io_read(io, buffer, length, offset)
276
+ total = 0
277
+ io.nonblock = true
278
+
279
+ while true
280
+ maximum_size = buffer.size - offset
281
+ result = blocking{buffer.read(io, maximum_size, offset)}
282
+
283
+ if result > 0
284
+ total += result
285
+ offset += result
286
+ break if total >= length
287
+ elsif result == 0
288
+ break
289
+ elsif result == EAGAIN
290
+ if length > 0
291
+ self.io_wait(io, IO::READABLE, nil)
292
+ else
293
+ return result
294
+ end
295
+ elsif result < 0
296
+ return result
297
+ end
298
+ end
299
+
300
+ return total
301
+ end
302
+
303
+ def io_write(io, buffer, length, offset)
304
+ total = 0
305
+ io.nonblock = true
306
+
307
+ while true
308
+ maximum_size = buffer.size - offset
309
+ result = blocking{buffer.write(io, maximum_size, offset)}
310
+
311
+ if result > 0
312
+ total += result
313
+ offset += result
314
+ break if total >= length
315
+ elsif result == 0
316
+ break
317
+ elsif result == EAGAIN
318
+ if length > 0
319
+ self.io_wait(io, IO::WRITABLE, nil)
320
+ else
321
+ return result
322
+ end
323
+ elsif result < 0
324
+ return result
325
+ end
326
+ end
327
+
328
+ return total
329
+ end
330
+
331
+ def blocking(&block)
332
+ Fiber.blocking(&block)
333
+ end
334
+ end
335
+
336
+ class BrokenUnblockScheduler < Scheduler
337
+ def unblock(blocker, fiber)
338
+ super
339
+
340
+ raise "Broken unblock!"
341
+ end
342
+ end
343
+
344
+ class SleepingUnblockScheduler < Scheduler
345
+ # This method is invoked when the thread is exiting.
346
+ def unblock(blocker, fiber)
347
+ super
348
+
349
+ # This changes the current thread state to `THREAD_RUNNING` which causes `thread_join_sleep` to hang.
350
+ sleep(0.1)
351
+ end
352
+ end
353
+
354
+ class SleepingBlockingScheduler < Scheduler
355
+ def kernel_sleep(duration = nil)
356
+ # Deliberaly sleep in a blocking state which can trigger a deadlock if the implementation is not correct.
357
+ Fiber.blocking{sleep 0.0001}
358
+
359
+ self.block(:sleep, duration)
360
+
361
+ return true
362
+ end
363
+ end
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  class SingletonTest < TestCase
28
28
  def test_singleton
29
- result = RubyProf.profile do
29
+ result = RubyProf::Profile.profile do
30
30
  a = A.new
31
31
  a << :first_thing
32
32
  assert_equal(1, a.as.size)
@@ -27,16 +27,12 @@ class STPT
27
27
  end
28
28
 
29
29
  class StackPrinterTest < TestCase
30
- def setup
31
- # Need to use wall time for this test due to the sleep calls
32
- RubyProf::measure_mode = RubyProf::WALL_TIME
33
- end
34
-
35
30
  def test_stack_can_be_printed
36
31
  start_time = Time.now
37
- RubyProf.start
38
- 5.times{STPT.new.a}
39
- result = RubyProf.stop
32
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
+ 5.times{STPT.new.a}
34
+ end
35
+
40
36
  end_time = Time.now
41
37
  expected_time = end_time - start_time
42
38
 
@@ -50,6 +46,7 @@ class StackPrinterTest < TestCase
50
46
  end
51
47
 
52
48
  private
49
+
53
50
  def print(result)
54
51
  test = caller.first =~ /in `(.*)'/ ? $1 : "test"
55
52
  testfile_name = "#{Dir.tmpdir}/ruby_prof_#{test}.html"
@@ -5,37 +5,34 @@ require File.expand_path('../test_helper', __FILE__)
5
5
 
6
6
  class StartStopTest < TestCase
7
7
  def setup
8
+ super
8
9
  # Need to use wall time for this test due to the sleep calls
9
- RubyProf::measure_mode = RubyProf::WALL_TIME
10
+ @profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
10
11
  end
11
12
 
12
13
  def method1
13
- RubyProf.start
14
- method2
14
+ @profile.start
15
+ method2
15
16
  end
16
17
 
17
18
  def method2
18
- method3
19
+ method3
19
20
  end
20
21
 
21
22
  def method3
22
23
  sleep(2)
23
- @result = RubyProf.stop
24
+ @result = @profile.stop
24
25
  end
25
26
 
26
27
  def test_extra_stop_should_raise
27
- RubyProf.start
28
+ @profile.start
28
29
  assert_raises(RuntimeError) do
29
- RubyProf.start
30
+ @profile.start
30
31
  end
31
32
 
33
+ @profile.stop # ok
32
34
  assert_raises(RuntimeError) do
33
- RubyProf.profile {}
34
- end
35
-
36
- RubyProf.stop # ok
37
- assert_raises(RuntimeError) do
38
- RubyProf.stop
35
+ @profile.stop
39
36
  end
40
37
  end
41
38
 
@@ -43,7 +40,7 @@ class StartStopTest < TestCase
43
40
  method1
44
41
 
45
42
  # Ruby prof should be stopped
46
- assert_equal(false, RubyProf.running?)
43
+ assert_equal(false, @profile.running?)
47
44
 
48
45
  methods = @result.threads.first.methods.sort.reverse
49
46
  assert_equal(4, methods.length)
data/test/test_helper.rb CHANGED
@@ -1,17 +1,20 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ # To make testing/debugging easier test within this source tree versus an installed gem
3
4
  require 'bundler/setup'
4
- require 'minitest/autorun'
5
5
 
6
- # Disable minitest parallel tests. The problem is the thread switching will change test results
7
- # (self vs wait time)
8
- if Gem::Version.new(Minitest::VERSION) > Gem::Version.new('5.11.3')
9
- ENV["MT_CPU"] = "0" # Newer versions minitest
10
- else
11
- ENV["N"] = "0" # Older versions of minitest
12
- end
6
+ # Add ext directory to load path to make it easier to test locally built extensions
7
+ ext_path = File.expand_path(File.join(__dir__, '..', 'ext', 'ruby_prof'))
8
+ $LOAD_PATH.unshift(File.expand_path(ext_path))
13
9
 
10
+ # Now load code
14
11
  require 'ruby-prof'
15
12
 
13
+ # Disable minitest parallel tests. The problem is the thread switching will change test results
14
+ # (self vs wait time)
15
+ ENV["MT_CPU"] = "0" # New versions of minitest
16
+ ENV["N"] = "0" # Older versions of minitest
17
+
18
+ require 'minitest/autorun'
16
19
  class TestCase < Minitest::Test
17
20
  end
data/test/thread_test.rb CHANGED
@@ -4,33 +4,122 @@
4
4
  require File.expand_path('../test_helper', __FILE__)
5
5
  require 'timeout'
6
6
  require 'benchmark'
7
+ require_relative './call_tree_builder'
7
8
 
8
9
  # -- Tests ----
9
10
  class ThreadTest < TestCase
10
- def setup
11
- # Need to use wall time for this test due to the sleep calls
12
- RubyProf::measure_mode = RubyProf::WALL_TIME
11
+ def test_initialize
12
+ method_info = RubyProf::MethodInfo.new(Array, :size)
13
+ call_tree = RubyProf::CallTree.new(method_info)
14
+ thread = RubyProf::Thread.new(call_tree, Thread.current, Fiber.current)
15
+
16
+ assert_equal(call_tree, thread.call_tree)
17
+ assert(thread)
18
+ assert(thread.id)
19
+ assert(thread.fiber_id)
20
+
21
+ assert_equal(1, thread.methods.size)
22
+ assert_same(method_info, thread.methods[0])
23
+ end
24
+
25
+ def test_merge
26
+ call_tree_1 = create_call_tree_1
27
+ thread_1 = RubyProf::Thread.new(call_tree_1, Thread.current, Fiber.current)
28
+ assert_equal(6, thread_1.methods.size)
29
+
30
+ call_tree_2 = create_call_tree_2
31
+ thread_2 = RubyProf::Thread.new(call_tree_2, Thread.current, Fiber.current)
32
+ assert_equal(6, thread_2.methods.size)
33
+
34
+ thread_1.merge!(thread_2)
35
+ assert_equal(7, thread_1.methods.size)
36
+
37
+ # Method times
38
+ assert_in_delta(11.6, thread_1.methods[0].total_time, 0.00001) # root
39
+ assert_in_delta(4.1, thread_1.methods[1].total_time, 0.00001) # a
40
+ assert_in_delta(1.5, thread_1.methods[2].total_time, 0.00001) # aa
41
+ assert_in_delta(2.6, thread_1.methods[3].total_time, 0.00001) # ab
42
+ assert_in_delta(7.5, thread_1.methods[4].total_time, 0.00001) # b
43
+ assert_in_delta(6.6, thread_1.methods[5].total_time, 0.00001) # bb
44
+ assert_in_delta(0.9, thread_1.methods[6].total_time, 0.00001) # ba
45
+
46
+ # Root
47
+ call_tree = call_tree_1
48
+ assert_equal(:root, call_tree.target.method_name)
49
+ assert_in_delta(11.6, call_tree.total_time, 0.00001)
50
+ assert_in_delta(0, call_tree.self_time, 0.00001)
51
+ assert_in_delta(0.0, call_tree.wait_time, 0.00001)
52
+ assert_in_delta(11.6, call_tree.children_time, 0.00001)
53
+
54
+ # a
55
+ call_tree = call_tree_1.children[0]
56
+ assert_equal(:a, call_tree.target.method_name)
57
+ assert_in_delta(4.1, call_tree.total_time, 0.00001)
58
+ assert_in_delta(0, call_tree.self_time, 0.00001)
59
+ assert_in_delta(0.0, call_tree.wait_time, 0.00001)
60
+ assert_in_delta(4.1, call_tree.children_time, 0.00001)
61
+
62
+ # aa
63
+ call_tree = call_tree_1.children[0].children[0]
64
+ assert_equal(:aa, call_tree.target.method_name)
65
+ assert_in_delta(1.5, call_tree.total_time, 0.00001)
66
+ assert_in_delta(1.5, call_tree.self_time, 0.00001)
67
+ assert_in_delta(0.0, call_tree.wait_time, 0.00001)
68
+ assert_in_delta(0.0, call_tree.children_time, 0.00001)
69
+
70
+ # ab
71
+ call_tree = call_tree_1.children[0].children[1]
72
+ assert_equal(:ab, call_tree.target.method_name)
73
+ assert_in_delta(2.6, call_tree.total_time, 0.00001)
74
+ assert_in_delta(2.6, call_tree.self_time, 0.00001)
75
+ assert_in_delta(0.0, call_tree.wait_time, 0.00001)
76
+ assert_in_delta(0.0, call_tree.children_time, 0.00001)
77
+
78
+ # # b
79
+ # call_tree = call_tree_1.children[1]
80
+ # assert_equal(:b, call_tree.target.method_name)
81
+ # assert_in_delta(7.5, call_tree.total_time, 0.00001)
82
+ # assert_in_delta(0, call_tree.self_time, 0.00001)
83
+ # assert_in_delta(0.0, call_tree.wait_time, 0.00001)
84
+ # assert_in_delta(7.5, call_tree.children_time, 0.00001)
85
+
86
+ # bb
87
+ # call_tree = call_tree_1.children[1].children[0]
88
+ # assert_equal(:bb, call_tree.target.method_name)
89
+ # assert_in_delta(6.6, call_tree.total_time, 0.00001)
90
+ # assert_in_delta(6.6, call_tree.self_time, 0.00001)
91
+ # assert_in_delta(0.0, call_tree.wait_time, 0.00001)
92
+ # assert_in_delta(0.0, call_tree.children_time, 0.00001)
93
+
94
+ # ba
95
+ call_tree = call_tree_1.children[1].children[1]
96
+ assert_equal(:ba, call_tree.target.method_name)
97
+ assert_in_delta(0.9, call_tree.total_time, 0.00001)
98
+ assert_in_delta(0.7, call_tree.self_time, 0.00001)
99
+ assert_in_delta(0.2, call_tree.wait_time, 0.00001)
100
+ assert_in_delta(0.0, call_tree.children_time, 0.00001)
13
101
  end
14
102
 
15
103
  def test_thread_count
16
- RubyProf.start
104
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
105
+ thread = Thread.new do
106
+ sleep(1)
107
+ end
17
108
 
18
- thread = Thread.new do
19
- sleep(1)
109
+ thread.join
20
110
  end
21
-
22
- thread.join
23
- result = RubyProf.stop
24
111
  assert_equal(2, result.threads.length)
25
112
  end
26
113
 
27
114
  def test_thread_identity
28
- RubyProf.start
115
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
116
+ profile.start
117
+
29
118
  sleep_thread = Thread.new do
30
119
  sleep(1)
31
120
  end
32
121
  sleep_thread.join
33
- result = RubyProf.stop
122
+ result = profile.stop
34
123
 
35
124
  thread_ids = result.threads.map {|thread| thread.id}.sort
36
125
  threads = [Thread.current, sleep_thread]
@@ -47,7 +136,9 @@ class ThreadTest < TestCase
47
136
  end
48
137
 
49
138
  def test_thread_timings
50
- RubyProf.start
139
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
140
+ profile.start
141
+
51
142
  thread = Thread.new do
52
143
  sleep 0
53
144
  # force it to hit thread.join, below, first
@@ -57,7 +148,7 @@ class ThreadTest < TestCase
57
148
  sleep(1)
58
149
  end
59
150
  thread.join
60
- result = RubyProf.stop
151
+ result = profile.stop
61
152
 
62
153
  # Check background thread
63
154
  assert_equal(2, result.threads.length)
@@ -71,10 +162,10 @@ class ThreadTest < TestCase
71
162
  method = methods[0]
72
163
  assert_equal('ThreadTest#test_thread_timings', method.full_name)
73
164
  assert_equal(1, method.called)
74
- assert_in_delta(1, method.total_time, 0.05)
165
+ assert_in_delta(1, method.total_time, 0.1)
75
166
  assert_in_delta(0, method.self_time, 0.05)
76
167
  assert_in_delta(0, method.wait_time, 0.05)
77
- assert_in_delta(1, method.children_time, 0.05)
168
+ assert_in_delta(1, method.children_time, 0.1)
78
169
  assert_equal(0, method.call_trees.callers.length)
79
170
 
80
171
  method = methods[1]