airbnb-ruby-prof 0.0.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 +483 -0
- data/LICENSE +25 -0
- data/README.rdoc +426 -0
- data/Rakefile +51 -0
- data/bin/ruby-prof +279 -0
- data/bin/ruby-prof-check-trace +45 -0
- data/examples/flat.txt +50 -0
- data/examples/graph.dot +84 -0
- data/examples/graph.html +823 -0
- data/examples/graph.txt +139 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +760 -0
- data/examples/multi.grind.dat +114 -0
- data/examples/multi.stack.html +547 -0
- data/examples/stack.html +547 -0
- data/ext/ruby_prof/extconf.rb +67 -0
- data/ext/ruby_prof/rp_call_info.c +374 -0
- data/ext/ruby_prof/rp_call_info.h +59 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
- data/ext/ruby_prof/rp_measure.c +71 -0
- data/ext/ruby_prof/rp_measure.h +56 -0
- data/ext/ruby_prof/rp_measure_allocations.c +74 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
- data/ext/ruby_prof/rp_measure_memory.c +75 -0
- data/ext/ruby_prof/rp_measure_process_time.c +69 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
- data/ext/ruby_prof/rp_method.c +717 -0
- data/ext/ruby_prof/rp_method.h +79 -0
- data/ext/ruby_prof/rp_stack.c +221 -0
- data/ext/ruby_prof/rp_stack.h +81 -0
- data/ext/ruby_prof/rp_thread.c +312 -0
- data/ext/ruby_prof/rp_thread.h +36 -0
- data/ext/ruby_prof/ruby_prof.c +800 -0
- data/ext/ruby_prof/ruby_prof.h +64 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
- data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
- data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
- data/lib/ruby-prof.rb +63 -0
- data/lib/ruby-prof/aggregate_call_info.rb +76 -0
- data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
- data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
- data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
- data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
- data/lib/ruby-prof/call_info.rb +111 -0
- data/lib/ruby-prof/call_info_visitor.rb +40 -0
- data/lib/ruby-prof/compatibility.rb +186 -0
- data/lib/ruby-prof/method_info.rb +109 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
- data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
- data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
- data/lib/ruby-prof/printers/flat_printer.rb +70 -0
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
- data/lib/ruby-prof/printers/graph_printer.rb +116 -0
- data/lib/ruby-prof/printers/multi_printer.rb +58 -0
- data/lib/ruby-prof/profile.rb +22 -0
- data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
- data/lib/ruby-prof/rack.rb +95 -0
- data/lib/ruby-prof/task.rb +147 -0
- data/lib/ruby-prof/thread.rb +35 -0
- data/lib/ruby-prof/version.rb +4 -0
- data/lib/ruby-prof/walker.rb +95 -0
- data/lib/unprof.rb +10 -0
- data/ruby-prof.gemspec +56 -0
- data/test/aggregate_test.rb +136 -0
- data/test/basic_test.rb +128 -0
- data/test/block_test.rb +74 -0
- data/test/call_info_test.rb +78 -0
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/dynamic_method_test.rb +55 -0
- data/test/enumerable_test.rb +21 -0
- data/test/exceptions_test.rb +16 -0
- data/test/exclude_methods_test.rb +146 -0
- data/test/exclude_threads_test.rb +53 -0
- data/test/fiber_test.rb +79 -0
- data/test/issue137_test.rb +63 -0
- data/test/line_number_test.rb +71 -0
- data/test/measure_allocations_test.rb +26 -0
- data/test/measure_cpu_time_test.rb +213 -0
- data/test/measure_gc_runs_test.rb +32 -0
- data/test/measure_gc_time_test.rb +36 -0
- data/test/measure_memory_test.rb +33 -0
- data/test/measure_process_time_test.rb +63 -0
- data/test/measure_wall_time_test.rb +255 -0
- data/test/module_test.rb +45 -0
- data/test/multi_measure_test.rb +38 -0
- data/test/multi_printer_test.rb +83 -0
- data/test/no_method_class_test.rb +15 -0
- data/test/pause_resume_test.rb +166 -0
- data/test/prime.rb +54 -0
- data/test/printers_test.rb +255 -0
- data/test/printing_recursive_graph_test.rb +127 -0
- data/test/rack_test.rb +93 -0
- data/test/recursive_test.rb +212 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +65 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +112 -0
- data/test/test_helper.rb +264 -0
- data/test/thread_test.rb +187 -0
- data/test/unique_call_path_test.rb +202 -0
- data/test/yarv_test.rb +55 -0
- metadata +211 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
|
7
|
+
# -- Tests ----
|
8
|
+
class ExcludeThreadsTest < TestCase
|
9
|
+
def test_exclude_threads
|
10
|
+
|
11
|
+
def thread1_proc
|
12
|
+
sleep(0.5)
|
13
|
+
sleep(2)
|
14
|
+
end
|
15
|
+
|
16
|
+
def thread2_proc
|
17
|
+
sleep(0.5)
|
18
|
+
sleep(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
thread1 = Thread.new do
|
22
|
+
thread1_proc
|
23
|
+
end
|
24
|
+
|
25
|
+
thread2 = Thread.new do
|
26
|
+
thread2_proc
|
27
|
+
end
|
28
|
+
|
29
|
+
# exclude_threads already includes the minitest thread pool
|
30
|
+
RubyProf.exclude_threads += [ thread2 ]
|
31
|
+
|
32
|
+
RubyProf.start
|
33
|
+
|
34
|
+
thread1.join
|
35
|
+
thread2.join
|
36
|
+
|
37
|
+
result = RubyProf.stop
|
38
|
+
|
39
|
+
assert_equal(2, result.threads.length)
|
40
|
+
|
41
|
+
output = Array.new
|
42
|
+
result.threads.each do |thread|
|
43
|
+
thread.methods.each do | m |
|
44
|
+
if m.full_name.index("ExcludeThreadsTest#thread") == 0
|
45
|
+
output.push(m.full_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_equal(1, output.length)
|
51
|
+
assert_equal("ExcludeThreadsTest#thread1_proc", output[0])
|
52
|
+
end
|
53
|
+
end
|
data/test/fiber_test.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
require 'timeout'
|
6
|
+
require 'set'
|
7
|
+
begin
|
8
|
+
require 'fiber'
|
9
|
+
rescue LoadError
|
10
|
+
end
|
11
|
+
|
12
|
+
# -- Tests ----
|
13
|
+
class FiberTest < TestCase
|
14
|
+
|
15
|
+
def fiber_test
|
16
|
+
@fiber_ids << Fiber.current.object_id
|
17
|
+
enum = Enumerator.new do |yielder|
|
18
|
+
[1,2].each do |x|
|
19
|
+
@fiber_ids << Fiber.current.object_id
|
20
|
+
sleep 0.1
|
21
|
+
yielder.yield x
|
22
|
+
end
|
23
|
+
end
|
24
|
+
while true
|
25
|
+
begin
|
26
|
+
enum.next
|
27
|
+
rescue StopIteration
|
28
|
+
break
|
29
|
+
end
|
30
|
+
end
|
31
|
+
sleep 0.1
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup
|
35
|
+
# Need to use wall time for this test due to the sleep calls
|
36
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
37
|
+
@fiber_ids = Set.new
|
38
|
+
@root_fiber = Fiber.current.object_id
|
39
|
+
@thread_id = Thread.current.object_id
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_fibers
|
43
|
+
result = RubyProf.profile { fiber_test }
|
44
|
+
profiled_fiber_ids = result.threads.map(&:fiber_id)
|
45
|
+
assert_equal(2, result.threads.length)
|
46
|
+
assert_equal([@thread_id], result.threads.map(&:id).uniq)
|
47
|
+
assert_equal(@fiber_ids, Set.new(profiled_fiber_ids))
|
48
|
+
|
49
|
+
assert profiled_fiber_ids.include?(@root_fiber)
|
50
|
+
assert(root_fiber_profile = result.threads.detect{|t| t.fiber_id == @root_fiber})
|
51
|
+
assert(enum_fiber_profile = result.threads.detect{|t| t.fiber_id != @root_fiber})
|
52
|
+
|
53
|
+
assert_in_delta(0.3, root_fiber_profile.total_time, 0.05)
|
54
|
+
assert_in_delta(0.2, enum_fiber_profile.total_time, 0.05)
|
55
|
+
|
56
|
+
assert(method_next = root_fiber_profile.methods.detect{|m| m.full_name == "Enumerator#next"})
|
57
|
+
assert(method_each = enum_fiber_profile.methods.detect{|m| m.full_name == "Enumerator#each"})
|
58
|
+
|
59
|
+
assert_in_delta(0.2, method_next.total_time, 0.05)
|
60
|
+
assert_in_delta(0.2, method_each.total_time, 0.05)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_merged_fibers
|
64
|
+
result = RubyProf.profile(merge_fibers: true) { fiber_test }
|
65
|
+
assert_equal(1, result.threads.length)
|
66
|
+
|
67
|
+
profile = result.threads.first
|
68
|
+
assert_equal 0, profile.fiber_id
|
69
|
+
|
70
|
+
assert_in_delta(0.3, profile.total_time, 0.05)
|
71
|
+
|
72
|
+
assert(method_next = profile.methods.detect{|m| m.full_name == "Enumerator#next"})
|
73
|
+
assert(method_each = profile.methods.detect{|m| m.full_name == "Enumerator#each"})
|
74
|
+
|
75
|
+
assert_in_delta(0.2, method_next.total_time, 0.05)
|
76
|
+
assert_in_delta(0.2, method_each.total_time, 0.05)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
# issue 137 is about correctly attributing time of recursive children
|
7
|
+
|
8
|
+
class RecursiveChildrenTest < TestCase
|
9
|
+
class SlowClass
|
10
|
+
def time_sink
|
11
|
+
1234567890 ** 100 == 0
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class SlowSearcher
|
16
|
+
def do_find(slow_objects)
|
17
|
+
slow_objects.find(&:time_sink)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class MainClass
|
22
|
+
def self.main_method
|
23
|
+
slow_objects = [SlowClass.new] * 100_000
|
24
|
+
slow_searcher = SlowSearcher.new
|
25
|
+
slow_searcher.do_find(slow_objects)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
include PrinterTestHelper
|
30
|
+
|
31
|
+
def setup
|
32
|
+
# Need to use wall time for this test due to the sleep calls
|
33
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_simple
|
37
|
+
result = RubyProf.profile do
|
38
|
+
# make array each recursive
|
39
|
+
[1].each do
|
40
|
+
MainClass.main_method
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# methods = result.threads.first.methods.sort.reverse
|
45
|
+
|
46
|
+
printer = RubyProf::GraphPrinter.new(result)
|
47
|
+
|
48
|
+
buffer = ''
|
49
|
+
printer.print(StringIO.new(buffer))
|
50
|
+
|
51
|
+
puts buffer if ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT'] == "1"
|
52
|
+
|
53
|
+
parsed_output = MetricsArray.parse(buffer)
|
54
|
+
|
55
|
+
assert( enum_find = parsed_output.metrics_for("Enumerable#find") )
|
56
|
+
assert( array_each = enum_find.child("Array#each") )
|
57
|
+
|
58
|
+
assert_operator enum_find.metrics.total, :>=, array_each.total
|
59
|
+
assert_operator enum_find.metrics.total, :>, 0
|
60
|
+
assert_in_delta enum_find.metrics.total, array_each.total, 0.02
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
class LineNumbers
|
7
|
+
def method1
|
8
|
+
end
|
9
|
+
|
10
|
+
def method2
|
11
|
+
method1
|
12
|
+
end
|
13
|
+
|
14
|
+
def method3
|
15
|
+
sleep(1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# -- Tests ----
|
20
|
+
class LineNumbersTest < TestCase
|
21
|
+
def test_function_line_no
|
22
|
+
numbers = LineNumbers.new
|
23
|
+
|
24
|
+
result = RubyProf.profile do
|
25
|
+
numbers.method2
|
26
|
+
end
|
27
|
+
|
28
|
+
methods = result.threads.first.methods.sort.reverse
|
29
|
+
assert_equal(3, methods.length)
|
30
|
+
|
31
|
+
method = methods[0]
|
32
|
+
assert_equal('LineNumbersTest#test_function_line_no', method.full_name)
|
33
|
+
assert_equal(25, method.line)
|
34
|
+
|
35
|
+
method = methods[1]
|
36
|
+
assert_equal('LineNumbers#method2', method.full_name)
|
37
|
+
assert_equal(10, method.line)
|
38
|
+
|
39
|
+
method = methods[2]
|
40
|
+
assert_equal('LineNumbers#method1', method.full_name)
|
41
|
+
assert_equal(7, method.line)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_c_function
|
45
|
+
numbers = LineNumbers.new
|
46
|
+
|
47
|
+
result = RubyProf.profile do
|
48
|
+
numbers.method3
|
49
|
+
end
|
50
|
+
|
51
|
+
methods = result.threads.first.methods.sort_by {|method| method.full_name}
|
52
|
+
assert_equal(3, methods.length)
|
53
|
+
|
54
|
+
# Methods:
|
55
|
+
# LineNumbers#method3
|
56
|
+
# LineNumbersTest#test_c_function
|
57
|
+
# Kernel#sleep
|
58
|
+
|
59
|
+
method = methods[0]
|
60
|
+
assert_equal('Kernel#sleep', method.full_name)
|
61
|
+
assert_equal(0, method.line)
|
62
|
+
|
63
|
+
method = methods[1]
|
64
|
+
assert_equal('LineNumbers#method3', method.full_name)
|
65
|
+
assert_equal(14, method.line)
|
66
|
+
|
67
|
+
method = methods[2]
|
68
|
+
assert_equal('LineNumbersTest#test_c_function', method.full_name)
|
69
|
+
assert_equal(48, method.line)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
class MeasureAllocationsTest < TestCase
|
7
|
+
def test_allocations_mode
|
8
|
+
RubyProf::measure_mode = RubyProf::ALLOCATIONS
|
9
|
+
assert_equal(RubyProf::ALLOCATIONS, RubyProf::measure_mode)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_allocations_enabled_defined
|
13
|
+
assert(defined?(RubyProf::ALLOCATIONS_ENABLED))
|
14
|
+
end
|
15
|
+
|
16
|
+
if RubyProf::ALLOCATIONS_ENABLED
|
17
|
+
def test_allocations
|
18
|
+
t = RubyProf.measure_allocations
|
19
|
+
refute_empty("a" + "b")
|
20
|
+
u = RubyProf.measure_allocations
|
21
|
+
assert_kind_of Integer, t
|
22
|
+
assert_kind_of Integer, u
|
23
|
+
assert_operator t, :<, u
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
class MeasureCpuTimeTest < TestCase
|
7
|
+
def setup
|
8
|
+
RubyProf::measure_mode = RubyProf::CPU_TIME
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_mode
|
16
|
+
assert_equal(RubyProf::CPU_TIME, RubyProf::measure_mode)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_cpu_time_enabled_defined
|
20
|
+
assert(defined?(RubyProf::CPU_TIME_ENABLED))
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_class_methods
|
24
|
+
result = RubyProf.profile do
|
25
|
+
RubyProf::C7.busy_wait
|
26
|
+
end
|
27
|
+
|
28
|
+
# Length should be greater 2:
|
29
|
+
# MeasureCpuTimeTest#test_class_methods
|
30
|
+
# <Class::RubyProf::C1>#busy_wait
|
31
|
+
# ....
|
32
|
+
|
33
|
+
methods = result.threads.first.methods.sort.reverse[0..1]
|
34
|
+
assert_equal(2, methods.length)
|
35
|
+
|
36
|
+
# Check the names
|
37
|
+
assert_equal('MeasureCpuTimeTest#test_class_methods', methods[0].full_name)
|
38
|
+
assert_equal('<Class::RubyProf::C7>#busy_wait', methods[1].full_name)
|
39
|
+
|
40
|
+
# Check times
|
41
|
+
assert_in_delta(0.1, methods[0].total_time, 0.05)
|
42
|
+
assert_in_delta(0, methods[0].wait_time, 0.05)
|
43
|
+
assert_in_delta(0, methods[0].self_time, 0.05)
|
44
|
+
|
45
|
+
assert_in_delta(0.1, methods[1].total_time, 0.05)
|
46
|
+
assert_in_delta(0, methods[1].wait_time, 0.05)
|
47
|
+
assert_in_delta(0, methods[1].self_time, 0.05)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_instance_methods
|
51
|
+
result = RubyProf.profile do
|
52
|
+
RubyProf::C7.new.busy_wait
|
53
|
+
end
|
54
|
+
|
55
|
+
methods = result.threads.first.methods.sort.reverse[0..1]
|
56
|
+
assert_equal(2, methods.length)
|
57
|
+
|
58
|
+
# Methods at this point:
|
59
|
+
# MeasureCpuTimeTest#test_instance_methods
|
60
|
+
# C7#busy_wait
|
61
|
+
# ...
|
62
|
+
|
63
|
+
names = methods.map(&:full_name)
|
64
|
+
assert_equal('MeasureCpuTimeTest#test_instance_methods', names[0])
|
65
|
+
assert_equal('RubyProf::C7#busy_wait', names[1])
|
66
|
+
|
67
|
+
|
68
|
+
# Check times
|
69
|
+
assert_in_delta(0.2, methods[0].total_time, 0.03)
|
70
|
+
assert_in_delta(0, methods[0].wait_time, 0.03)
|
71
|
+
assert_in_delta(0, methods[0].self_time, 0.03)
|
72
|
+
|
73
|
+
assert_in_delta(0.2, methods[1].total_time, 0.03)
|
74
|
+
assert_in_delta(0, methods[1].wait_time, 0.03)
|
75
|
+
assert_in_delta(0, methods[1].self_time, 0.2)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_module_methods
|
79
|
+
result = RubyProf.profile do
|
80
|
+
RubyProf::C8.busy_wait
|
81
|
+
end
|
82
|
+
|
83
|
+
# Methods:
|
84
|
+
# MeasureCpuTimeTest#test_module_methods
|
85
|
+
# M1#busy_wait
|
86
|
+
# ...
|
87
|
+
|
88
|
+
methods = result.threads.first.methods.sort.reverse[0..1]
|
89
|
+
assert_equal(2, methods.length)
|
90
|
+
|
91
|
+
assert_equal('MeasureCpuTimeTest#test_module_methods', methods[0].full_name)
|
92
|
+
assert_equal('RubyProf::M7#busy_wait', methods[1].full_name)
|
93
|
+
|
94
|
+
# Check times
|
95
|
+
assert_in_delta(0.3, methods[0].total_time, 0.1)
|
96
|
+
assert_in_delta(0, methods[0].wait_time, 0.02)
|
97
|
+
assert_in_delta(0, methods[0].self_time, 0.02)
|
98
|
+
|
99
|
+
assert_in_delta(0.3, methods[1].total_time, 0.1)
|
100
|
+
assert_in_delta(0, methods[1].wait_time, 0.02)
|
101
|
+
assert_in_delta(0, methods[1].self_time, 0.1)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_module_instance_methods
|
105
|
+
result = RubyProf.profile do
|
106
|
+
RubyProf::C8.new.busy_wait
|
107
|
+
end
|
108
|
+
|
109
|
+
# Methods:
|
110
|
+
# MeasureCpuTimeTest#test_module_instance_methods
|
111
|
+
# M7#busy_wait
|
112
|
+
# ...
|
113
|
+
|
114
|
+
methods = result.threads.first.methods.sort.reverse[0..1]
|
115
|
+
assert_equal(2, methods.length)
|
116
|
+
names = methods.map(&:full_name)
|
117
|
+
assert_equal('MeasureCpuTimeTest#test_module_instance_methods', names[0])
|
118
|
+
assert_equal('RubyProf::M7#busy_wait', names[1])
|
119
|
+
|
120
|
+
# Check times
|
121
|
+
assert_in_delta(0.3, methods[0].total_time, 0.1)
|
122
|
+
assert_in_delta(0, methods[0].wait_time, 0.1)
|
123
|
+
assert_in_delta(0, methods[0].self_time, 0.1)
|
124
|
+
|
125
|
+
assert_in_delta(0.3, methods[1].total_time, 0.1)
|
126
|
+
assert_in_delta(0, methods[1].wait_time, 0.01)
|
127
|
+
assert_in_delta(0, methods[1].self_time, 0.1)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_singleton
|
131
|
+
c3 = RubyProf::C3.new
|
132
|
+
|
133
|
+
class << c3
|
134
|
+
def busy_wait
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
result = RubyProf.profile do
|
139
|
+
c3.busy_wait
|
140
|
+
end
|
141
|
+
|
142
|
+
methods = result.threads.first.methods.sort.reverse
|
143
|
+
assert_equal(2, methods.length)
|
144
|
+
|
145
|
+
assert_equal('MeasureCpuTimeTest#test_singleton', methods[0].full_name)
|
146
|
+
assert_equal('<Object::RubyProf::C3>#busy_wait', methods[1].full_name)
|
147
|
+
|
148
|
+
assert_in_delta(0, methods[0].total_time, 0.01)
|
149
|
+
assert_in_delta(0, methods[0].wait_time, 0.01)
|
150
|
+
assert_in_delta(0, methods[0].self_time, 0.01)
|
151
|
+
|
152
|
+
assert_in_delta(0, methods[1].total_time, 0.01)
|
153
|
+
assert_in_delta(0, methods[1].wait_time, 0.01)
|
154
|
+
assert_in_delta(0, methods[1].self_time, 0.01)
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def test_sleeping_does_accumulate_wall_time
|
159
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
160
|
+
result = RubyProf.profile do
|
161
|
+
sleep 0.1
|
162
|
+
end
|
163
|
+
methods = result.threads.first.methods.sort.reverse
|
164
|
+
assert_equal(["MeasureCpuTimeTest#test_sleeping_does_accumulate_wall_time", "Kernel#sleep"], methods.map(&:full_name))
|
165
|
+
assert_in_delta(0.1, methods[1].total_time, 0.01)
|
166
|
+
assert_equal(0, methods[1].wait_time)
|
167
|
+
assert_in_delta(0.1, methods[1].self_time, 0.01)
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_sleeping_does_not_accumulate_significant_cpu_time
|
171
|
+
result = RubyProf.profile do
|
172
|
+
sleep 0.1
|
173
|
+
end
|
174
|
+
methods = result.threads.first.methods.sort.reverse
|
175
|
+
assert_equal(["MeasureCpuTimeTest#test_sleeping_does_not_accumulate_significant_cpu_time", "Kernel#sleep"], methods.map(&:full_name))
|
176
|
+
assert_in_delta(0, methods[1].total_time, 0.01)
|
177
|
+
assert_equal(0, methods[1].wait_time)
|
178
|
+
assert_in_delta(0, methods[1].self_time, 0.01)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_waiting_for_threads_does_not_accumulate_cpu_time
|
182
|
+
background_thread = nil
|
183
|
+
result = RubyProf.profile do
|
184
|
+
background_thread = Thread.new{ sleep 0.1 }
|
185
|
+
background_thread.join
|
186
|
+
end
|
187
|
+
# check number of threads
|
188
|
+
assert_equal(2, result.threads.length)
|
189
|
+
fg, bg = result.threads
|
190
|
+
assert(fg.methods.map(&:full_name).include?("Thread#join"))
|
191
|
+
assert(bg.methods.map(&:full_name).include?("Kernel#sleep"))
|
192
|
+
assert_in_delta(0, fg.total_time, 0.01)
|
193
|
+
assert_in_delta(0, bg.total_time, 0.01)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_waiting_for_threads_does_accumulate_wall_time
|
197
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
198
|
+
background_thread = nil
|
199
|
+
result = RubyProf.profile do
|
200
|
+
background_thread = Thread.new{ sleep 0.1 }
|
201
|
+
background_thread.join
|
202
|
+
end
|
203
|
+
# check number of threads
|
204
|
+
assert_equal(2, result.threads.length)
|
205
|
+
fg, bg = result.threads
|
206
|
+
assert(fg.methods.map(&:full_name).include?("Thread#join"))
|
207
|
+
assert(bg.methods.map(&:full_name).include?("Kernel#sleep"))
|
208
|
+
assert_in_delta(0.1, fg.total_time, 0.01)
|
209
|
+
assert_in_delta(0.1, fg.wait_time, 0.01)
|
210
|
+
assert_in_delta(0.1, bg.total_time, 0.01)
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|