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.
Files changed (116) hide show
  1. data/CHANGES +483 -0
  2. data/LICENSE +25 -0
  3. data/README.rdoc +426 -0
  4. data/Rakefile +51 -0
  5. data/bin/ruby-prof +279 -0
  6. data/bin/ruby-prof-check-trace +45 -0
  7. data/examples/flat.txt +50 -0
  8. data/examples/graph.dot +84 -0
  9. data/examples/graph.html +823 -0
  10. data/examples/graph.txt +139 -0
  11. data/examples/multi.flat.txt +23 -0
  12. data/examples/multi.graph.html +760 -0
  13. data/examples/multi.grind.dat +114 -0
  14. data/examples/multi.stack.html +547 -0
  15. data/examples/stack.html +547 -0
  16. data/ext/ruby_prof/extconf.rb +67 -0
  17. data/ext/ruby_prof/rp_call_info.c +374 -0
  18. data/ext/ruby_prof/rp_call_info.h +59 -0
  19. data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
  20. data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
  21. data/ext/ruby_prof/rp_measure.c +71 -0
  22. data/ext/ruby_prof/rp_measure.h +56 -0
  23. data/ext/ruby_prof/rp_measure_allocations.c +74 -0
  24. data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
  25. data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
  26. data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
  27. data/ext/ruby_prof/rp_measure_memory.c +75 -0
  28. data/ext/ruby_prof/rp_measure_process_time.c +69 -0
  29. data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
  30. data/ext/ruby_prof/rp_method.c +717 -0
  31. data/ext/ruby_prof/rp_method.h +79 -0
  32. data/ext/ruby_prof/rp_stack.c +221 -0
  33. data/ext/ruby_prof/rp_stack.h +81 -0
  34. data/ext/ruby_prof/rp_thread.c +312 -0
  35. data/ext/ruby_prof/rp_thread.h +36 -0
  36. data/ext/ruby_prof/ruby_prof.c +800 -0
  37. data/ext/ruby_prof/ruby_prof.h +64 -0
  38. data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
  39. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
  40. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
  41. data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
  42. data/lib/ruby-prof.rb +63 -0
  43. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  45. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  46. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  47. data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
  48. data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
  49. data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
  50. data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
  51. data/lib/ruby-prof/call_info.rb +111 -0
  52. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  53. data/lib/ruby-prof/compatibility.rb +186 -0
  54. data/lib/ruby-prof/method_info.rb +109 -0
  55. data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
  56. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  57. data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
  58. data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
  59. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  60. data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
  61. data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
  62. data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
  63. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  64. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
  65. data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
  66. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  67. data/lib/ruby-prof/printers/multi_printer.rb +58 -0
  68. data/lib/ruby-prof/profile.rb +22 -0
  69. data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
  70. data/lib/ruby-prof/rack.rb +95 -0
  71. data/lib/ruby-prof/task.rb +147 -0
  72. data/lib/ruby-prof/thread.rb +35 -0
  73. data/lib/ruby-prof/version.rb +4 -0
  74. data/lib/ruby-prof/walker.rb +95 -0
  75. data/lib/unprof.rb +10 -0
  76. data/ruby-prof.gemspec +56 -0
  77. data/test/aggregate_test.rb +136 -0
  78. data/test/basic_test.rb +128 -0
  79. data/test/block_test.rb +74 -0
  80. data/test/call_info_test.rb +78 -0
  81. data/test/call_info_visitor_test.rb +31 -0
  82. data/test/duplicate_names_test.rb +32 -0
  83. data/test/dynamic_method_test.rb +55 -0
  84. data/test/enumerable_test.rb +21 -0
  85. data/test/exceptions_test.rb +16 -0
  86. data/test/exclude_methods_test.rb +146 -0
  87. data/test/exclude_threads_test.rb +53 -0
  88. data/test/fiber_test.rb +79 -0
  89. data/test/issue137_test.rb +63 -0
  90. data/test/line_number_test.rb +71 -0
  91. data/test/measure_allocations_test.rb +26 -0
  92. data/test/measure_cpu_time_test.rb +213 -0
  93. data/test/measure_gc_runs_test.rb +32 -0
  94. data/test/measure_gc_time_test.rb +36 -0
  95. data/test/measure_memory_test.rb +33 -0
  96. data/test/measure_process_time_test.rb +63 -0
  97. data/test/measure_wall_time_test.rb +255 -0
  98. data/test/module_test.rb +45 -0
  99. data/test/multi_measure_test.rb +38 -0
  100. data/test/multi_printer_test.rb +83 -0
  101. data/test/no_method_class_test.rb +15 -0
  102. data/test/pause_resume_test.rb +166 -0
  103. data/test/prime.rb +54 -0
  104. data/test/printers_test.rb +255 -0
  105. data/test/printing_recursive_graph_test.rb +127 -0
  106. data/test/rack_test.rb +93 -0
  107. data/test/recursive_test.rb +212 -0
  108. data/test/singleton_test.rb +38 -0
  109. data/test/stack_printer_test.rb +65 -0
  110. data/test/stack_test.rb +138 -0
  111. data/test/start_stop_test.rb +112 -0
  112. data/test/test_helper.rb +264 -0
  113. data/test/thread_test.rb +187 -0
  114. data/test/unique_call_path_test.rb +202 -0
  115. data/test/yarv_test.rb +55 -0
  116. 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
@@ -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