ruby-prof 1.4.4-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +608 -0
  3. data/LICENSE +25 -0
  4. data/README.md +5 -0
  5. data/Rakefile +98 -0
  6. data/bin/ruby-prof +328 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +22 -0
  9. data/ext/ruby_prof/rp_aggregate_call_tree.c +59 -0
  10. data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
  11. data/ext/ruby_prof/rp_allocation.c +287 -0
  12. data/ext/ruby_prof/rp_allocation.h +31 -0
  13. data/ext/ruby_prof/rp_call_tree.c +367 -0
  14. data/ext/ruby_prof/rp_call_tree.h +43 -0
  15. data/ext/ruby_prof/rp_call_trees.c +288 -0
  16. data/ext/ruby_prof/rp_call_trees.h +28 -0
  17. data/ext/ruby_prof/rp_measure_allocations.c +47 -0
  18. data/ext/ruby_prof/rp_measure_memory.c +46 -0
  19. data/ext/ruby_prof/rp_measure_process_time.c +66 -0
  20. data/ext/ruby_prof/rp_measure_wall_time.c +64 -0
  21. data/ext/ruby_prof/rp_measurement.c +237 -0
  22. data/ext/ruby_prof/rp_measurement.h +50 -0
  23. data/ext/ruby_prof/rp_method.c +491 -0
  24. data/ext/ruby_prof/rp_method.h +62 -0
  25. data/ext/ruby_prof/rp_profile.c +915 -0
  26. data/ext/ruby_prof/rp_profile.h +35 -0
  27. data/ext/ruby_prof/rp_stack.c +212 -0
  28. data/ext/ruby_prof/rp_stack.h +53 -0
  29. data/ext/ruby_prof/rp_thread.c +362 -0
  30. data/ext/ruby_prof/rp_thread.h +39 -0
  31. data/ext/ruby_prof/ruby_prof.c +52 -0
  32. data/ext/ruby_prof/ruby_prof.h +26 -0
  33. data/ext/ruby_prof/vc/ruby_prof.sln +39 -0
  34. data/ext/ruby_prof/vc/ruby_prof.vcxproj +160 -0
  35. data/lib/3.1/ruby_prof.so +0 -0
  36. data/lib/ruby-prof/assets/call_stack_printer.html.erb +711 -0
  37. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  38. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  39. data/lib/ruby-prof/call_tree.rb +57 -0
  40. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  41. data/lib/ruby-prof/compatibility.rb +99 -0
  42. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  43. data/lib/ruby-prof/measurement.rb +17 -0
  44. data/lib/ruby-prof/method_info.rb +78 -0
  45. data/lib/ruby-prof/printers/abstract_printer.rb +137 -0
  46. data/lib/ruby-prof/printers/call_info_printer.rb +53 -0
  47. data/lib/ruby-prof/printers/call_stack_printer.rb +180 -0
  48. data/lib/ruby-prof/printers/call_tree_printer.rb +147 -0
  49. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  50. data/lib/ruby-prof/printers/flat_printer.rb +53 -0
  51. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
  52. data/lib/ruby-prof/printers/graph_printer.rb +113 -0
  53. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  54. data/lib/ruby-prof/profile.rb +37 -0
  55. data/lib/ruby-prof/rack.rb +95 -0
  56. data/lib/ruby-prof/task.rb +147 -0
  57. data/lib/ruby-prof/thread.rb +20 -0
  58. data/lib/ruby-prof/version.rb +3 -0
  59. data/lib/ruby-prof.rb +52 -0
  60. data/lib/unprof.rb +10 -0
  61. data/ruby-prof.gemspec +64 -0
  62. data/test/abstract_printer_test.rb +26 -0
  63. data/test/alias_test.rb +122 -0
  64. data/test/basic_test.rb +43 -0
  65. data/test/call_tree_visitor_test.rb +32 -0
  66. data/test/call_trees_test.rb +66 -0
  67. data/test/duplicate_names_test.rb +32 -0
  68. data/test/dynamic_method_test.rb +67 -0
  69. data/test/enumerable_test.rb +21 -0
  70. data/test/exceptions_test.rb +24 -0
  71. data/test/exclude_methods_test.rb +151 -0
  72. data/test/exclude_threads_test.rb +53 -0
  73. data/test/fiber_test.rb +129 -0
  74. data/test/gc_test.rb +100 -0
  75. data/test/inverse_call_tree_test.rb +175 -0
  76. data/test/line_number_test.rb +158 -0
  77. data/test/marshal_test.rb +145 -0
  78. data/test/measure_allocations.rb +26 -0
  79. data/test/measure_allocations_test.rb +333 -0
  80. data/test/measure_memory_test.rb +688 -0
  81. data/test/measure_process_time_test.rb +1614 -0
  82. data/test/measure_times.rb +56 -0
  83. data/test/measure_wall_time_test.rb +426 -0
  84. data/test/multi_printer_test.rb +71 -0
  85. data/test/no_method_class_test.rb +15 -0
  86. data/test/pause_resume_test.rb +175 -0
  87. data/test/prime.rb +54 -0
  88. data/test/prime_script.rb +6 -0
  89. data/test/printer_call_stack_test.rb +27 -0
  90. data/test/printer_call_tree_test.rb +30 -0
  91. data/test/printer_flat_test.rb +99 -0
  92. data/test/printer_graph_html_test.rb +59 -0
  93. data/test/printer_graph_test.rb +40 -0
  94. data/test/printers_test.rb +141 -0
  95. data/test/printing_recursive_graph_test.rb +81 -0
  96. data/test/profile_test.rb +16 -0
  97. data/test/rack_test.rb +93 -0
  98. data/test/recursive_test.rb +430 -0
  99. data/test/singleton_test.rb +38 -0
  100. data/test/stack_printer_test.rb +64 -0
  101. data/test/start_stop_test.rb +109 -0
  102. data/test/test_helper.rb +13 -0
  103. data/test/thread_test.rb +144 -0
  104. data/test/unique_call_path_test.rb +136 -0
  105. data/test/yarv_test.rb +60 -0
  106. metadata +187 -0
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Test data
7
+ # A
8
+ # / \
9
+ # B C
10
+ # \
11
+ # B
12
+
13
+ class STPT
14
+ def a
15
+ 100.times{b}
16
+ 300.times{c}
17
+ c;c;c
18
+ end
19
+
20
+ def b
21
+ sleep 0
22
+ end
23
+
24
+ def c
25
+ 5.times{b}
26
+ end
27
+ end
28
+
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
+ def test_stack_can_be_printed
36
+ start_time = Time.now
37
+ RubyProf.start
38
+ 5.times{STPT.new.a}
39
+ result = RubyProf.stop
40
+ end_time = Time.now
41
+ expected_time = end_time - start_time
42
+
43
+ file_contents = nil
44
+ file_contents = print(result)
45
+ re = /Thread: (\d+)(, Fiber: (\d+))? \([\.0-9]+.[\.0-9]+% ~ ([\.0-9]+)\)/
46
+ assert_match(re, file_contents)
47
+ file_contents =~ re
48
+ actual_time = $4.to_f
49
+ assert_in_delta(expected_time, actual_time, 0.1)
50
+ end
51
+
52
+ private
53
+ def print(result)
54
+ test = caller.first =~ /in `(.*)'/ ? $1 : "test"
55
+ testfile_name = "#{Dir.tmpdir}/ruby_prof_#{test}.html"
56
+ # puts "printing to #{testfile_name}"
57
+ printer = RubyProf::CallStackPrinter.new(result)
58
+ File.open(testfile_name, "w") {|f| printer.print(f, :threshold => 0, :min_percent => 0, :title => "ruby_prof #{test}")}
59
+ system("open '#{testfile_name}'") if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
60
+ assert File.exist?(testfile_name), "#{testfile_name} does not exist"
61
+ assert File.readable?(testfile_name), "#{testfile_name} is no readable"
62
+ File.read(testfile_name)
63
+ end
64
+ end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class StartStopTest < TestCase
7
+ def setup
8
+ # Need to use wall time for this test due to the sleep calls
9
+ RubyProf::measure_mode = RubyProf::WALL_TIME
10
+ end
11
+
12
+ def method1
13
+ RubyProf.start
14
+ method2
15
+ end
16
+
17
+ def method2
18
+ method3
19
+ end
20
+
21
+ def method3
22
+ sleep(2)
23
+ @result = RubyProf.stop
24
+ end
25
+
26
+ def test_extra_stop_should_raise
27
+ RubyProf.start
28
+ assert_raises(RuntimeError) do
29
+ RubyProf.start
30
+ end
31
+
32
+ assert_raises(RuntimeError) do
33
+ RubyProf.profile {}
34
+ end
35
+
36
+ RubyProf.stop # ok
37
+ assert_raises(RuntimeError) do
38
+ RubyProf.stop
39
+ end
40
+ end
41
+
42
+ def test_different_methods
43
+ method1
44
+
45
+ # Ruby prof should be stopped
46
+ assert_equal(false, RubyProf.running?)
47
+
48
+ methods = @result.threads.first.methods.sort.reverse
49
+ assert_equal(4, methods.length)
50
+
51
+ method = methods[0]
52
+ assert_equal('StartStopTest#method1', method.full_name)
53
+ assert_equal(1, method.called)
54
+ assert_in_delta(2, method.total_time, 0.05)
55
+ assert_in_delta(0, method.wait_time, 0.02)
56
+ assert_in_delta(0, method.self_time, 0.02)
57
+ assert_in_delta(2, method.children_time, 0.05)
58
+
59
+ assert_equal(1, method.call_trees.callees.length)
60
+ call_tree = method.call_trees.callees[0]
61
+ assert_equal('StartStopTest#method2', call_tree.target.full_name)
62
+
63
+ method = methods[1]
64
+ assert_equal('StartStopTest#method2', method.full_name)
65
+ assert_equal(1, method.called)
66
+ assert_in_delta(2, method.total_time, 0.05)
67
+ assert_in_delta(0, method.wait_time, 0.02)
68
+ assert_in_delta(0, method.self_time, 0.02)
69
+ assert_in_delta(2, method.children_time, 0.05)
70
+
71
+ assert_equal(1, method.call_trees.callers.length)
72
+ call_tree = method.call_trees.callers[0]
73
+ assert_equal('StartStopTest#method1', call_tree.parent.target.full_name)
74
+
75
+ assert_equal(1, method.call_trees.callees.length)
76
+ call_tree = method.call_trees.callees[0]
77
+ assert_equal('StartStopTest#method3', call_tree.target.full_name)
78
+
79
+ method = methods[2]
80
+ assert_equal('StartStopTest#method3', method.full_name)
81
+ assert_equal(1, method.called)
82
+ assert_in_delta(2, method.total_time, 0.02)
83
+ assert_in_delta(0, method.wait_time, 0.02)
84
+ assert_in_delta(0, method.self_time, 0.02)
85
+ assert_in_delta(2, method.children_time, 0.02)
86
+
87
+ assert_equal(1, method.call_trees.callers.length)
88
+ call_tree = method.call_trees.callers[0]
89
+ assert_equal('StartStopTest#method2', call_tree.parent.target.full_name)
90
+
91
+ assert_equal(1, method.call_trees.callees.length)
92
+ call_tree = method.call_trees.callees[0]
93
+ assert_equal('Kernel#sleep', call_tree.target.full_name)
94
+
95
+ method = methods[3]
96
+ assert_equal('Kernel#sleep', method.full_name)
97
+ assert_equal(1, method.called)
98
+ assert_in_delta(2, method.total_time, 0.02)
99
+ assert_in_delta(0, method.wait_time, 0.02)
100
+ assert_in_delta(2, method.self_time, 0.02)
101
+ assert_in_delta(0, method.children_time, 0.02)
102
+
103
+ assert_equal(1, method.call_trees.callers.length)
104
+ call_tree = method.call_trees.callers[0]
105
+ assert_equal('StartStopTest#method3', call_tree.parent.target.full_name)
106
+
107
+ assert_equal(0, method.call_trees.callees.length)
108
+ end
109
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'bundler/setup'
4
+ require 'ruby-prof'
5
+
6
+ # Disable minitest parallel tests. The problem is the thread switching will change test results
7
+ # (self vs wait time)
8
+ ENV["MT_CPU"] = "0" # New versions of minitest
9
+ ENV["N"] = "0" # Older versions of minitest
10
+
11
+ require 'minitest/autorun'
12
+ class TestCase < Minitest::Test
13
+ end
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'timeout'
6
+ require 'benchmark'
7
+
8
+ # -- Tests ----
9
+ 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
13
+ end
14
+
15
+ def test_thread_count
16
+ RubyProf.start
17
+
18
+ thread = Thread.new do
19
+ sleep(1)
20
+ end
21
+
22
+ thread.join
23
+ result = RubyProf.stop
24
+ assert_equal(2, result.threads.length)
25
+ end
26
+
27
+ def test_thread_identity
28
+ RubyProf.start
29
+ sleep_thread = Thread.new do
30
+ sleep(1)
31
+ end
32
+ sleep_thread.join
33
+ result = RubyProf.stop
34
+
35
+ thread_ids = result.threads.map {|thread| thread.id}.sort
36
+ threads = [Thread.current, sleep_thread]
37
+ assert_equal(2, result.threads.length)
38
+
39
+ assert(thread_ids.include?(threads[0].object_id))
40
+ assert(thread_ids.include?(threads[1].object_id))
41
+
42
+ assert_instance_of(Thread, ObjectSpace._id2ref(thread_ids[0]))
43
+ assert(threads.include?(ObjectSpace._id2ref(thread_ids[0])))
44
+
45
+ assert_instance_of(Thread, ObjectSpace._id2ref(thread_ids[1]))
46
+ assert(threads.include?(ObjectSpace._id2ref(thread_ids[1])))
47
+ end
48
+
49
+ def test_thread_timings
50
+ RubyProf.start
51
+ thread = Thread.new do
52
+ sleep 0
53
+ # force it to hit thread.join, below, first
54
+ # thus forcing sleep(1), below, to be counted as (wall) self_time
55
+ # since we currently count time "in some other thread" as self.wait_time
56
+ # for whatever reason
57
+ sleep(1)
58
+ end
59
+ thread.join
60
+ result = RubyProf.stop
61
+
62
+ # Check background thread
63
+ assert_equal(2, result.threads.length)
64
+
65
+ rp_thread = result.threads.detect {|t| t.id == thread.object_id}
66
+ methods = rp_thread.methods.sort.reverse
67
+ # fails on travis. why?
68
+ # expected_methods = ["ThreadTest#test_thread_timings", "Kernel#sleep"]
69
+ # assert_equal(expected_methods, methods.map(&:full_name))
70
+
71
+ method = methods[0]
72
+ assert_equal('ThreadTest#test_thread_timings', method.full_name)
73
+ assert_equal(1, method.called)
74
+ assert_in_delta(1, method.total_time, 0.05)
75
+ assert_in_delta(0, method.self_time, 0.05)
76
+ assert_in_delta(0, method.wait_time, 0.05)
77
+ assert_in_delta(1, method.children_time, 0.05)
78
+ assert_equal(0, method.call_trees.callers.length)
79
+
80
+ method = methods[1]
81
+ assert_equal('Kernel#sleep', method.full_name)
82
+ assert_equal(2, method.called)
83
+ assert_in_delta(1, method.total_time, 0.05)
84
+ assert_in_delta(1.0, method.self_time, 0.05)
85
+ assert_in_delta(0, method.wait_time, 0.05)
86
+ assert_in_delta(0, method.children_time, 0.05)
87
+
88
+ assert_equal(1, method.call_trees.callers.length)
89
+ assert_equal(0, method.call_trees.callees.length)
90
+
91
+ # Check foreground thread
92
+ rp_thread = result.threads.detect {|athread| athread.id == Thread.current.object_id}
93
+ methods = rp_thread.methods.sort.reverse
94
+ assert_equal(4, methods.length)
95
+ methods = methods.sort.reverse
96
+
97
+ method = methods[0]
98
+ assert_equal('ThreadTest#test_thread_timings', method.full_name)
99
+ # the sub calls to Object#new, when popped,
100
+ # cause the parent frame to be created for method #test_thread_timings, which means a +1 when it's popped in the end
101
+ # xxxx a test that shows it the other way, too (never creates parent frame--if that's even possible)
102
+ assert_equal(1, method.called)
103
+ assert_in_delta(1, method.total_time, 0.05)
104
+ assert_in_delta(0, method.self_time, 0.05)
105
+ assert_in_delta(0, method.wait_time, 0.05)
106
+ assert_in_delta(1, method.children_time, 0.05)
107
+
108
+ assert_equal(0, method.call_trees.callers.length)
109
+ assert_equal(2, method.call_trees.callees.length)
110
+
111
+ method = methods[1]
112
+ assert_equal('Thread#join', method.full_name)
113
+ assert_equal(1, method.called)
114
+ assert_in_delta(1, method.total_time, 0.05)
115
+ assert_in_delta(0, method.self_time, 0.05)
116
+ assert_in_delta(1.0, method.wait_time, 0.05)
117
+ assert_in_delta(0, method.children_time, 0.05)
118
+
119
+ assert_equal(1, method.call_trees.callers.length)
120
+ assert_equal(0, method.call_trees.callees.length)
121
+
122
+ method = methods[2]
123
+ assert_equal('<Class::Thread>#new', method.full_name)
124
+ assert_equal(1, method.called)
125
+ assert_in_delta(0, method.total_time, 0.05)
126
+ assert_in_delta(0, method.self_time, 0.05)
127
+ assert_in_delta(0, method.wait_time, 0.05)
128
+ assert_in_delta(0, method.children_time, 0.05)
129
+
130
+ assert_equal(1, method.call_trees.callers.length)
131
+ assert_equal(1, method.call_trees.callees.length)
132
+
133
+ method = methods[3]
134
+ assert_equal('Thread#initialize', method.full_name)
135
+ assert_equal(1, method.called)
136
+ assert_in_delta(0, method.total_time, 0.05)
137
+ assert_in_delta(0, method.self_time, 0.05)
138
+ assert_in_delta(0, method.wait_time, 0.05)
139
+ assert_in_delta(0, method.children_time, 0.05)
140
+
141
+ assert_equal(1, method.call_trees.callers.length)
142
+ assert_equal(0, method.call_trees.callees.length)
143
+ end
144
+ end
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class UniqueCallPath
7
+ def method_a(i)
8
+ if i==1
9
+ method_b
10
+ else
11
+ method_c
12
+ end
13
+ end
14
+
15
+ def method_b
16
+ method_c
17
+ end
18
+
19
+ def method_c
20
+ end
21
+
22
+ def method_k(i)
23
+ method_a(i)
24
+ end
25
+ end
26
+
27
+
28
+ # -- Tests ----
29
+ class UniqueCallPathTest < TestCase
30
+ def test_root
31
+ unique_call_path = UniqueCallPath.new
32
+
33
+ result = RubyProf.profile do
34
+ unique_call_path.method_a(1)
35
+ end
36
+
37
+ root_call_info = result.threads.first.call_tree
38
+ assert_equal("UniqueCallPathTest#test_root", root_call_info.target.full_name)
39
+ end
40
+
41
+ def test_root_children
42
+ unique_call_path = UniqueCallPath.new
43
+
44
+ result = RubyProf.profile do
45
+ unique_call_path.method_a(1)
46
+ unique_call_path.method_k(2)
47
+ end
48
+
49
+ root_call_info = result.threads.first.call_tree
50
+ children = root_call_info.children.sort do |c1, c2|
51
+ c1.target.full_name <=> c2.target.full_name
52
+ end
53
+
54
+ assert_equal(2, children.length)
55
+ assert_equal("UniqueCallPath#method_a", children[0].target.full_name)
56
+ assert_equal("UniqueCallPath#method_k", children[1].target.full_name)
57
+ end
58
+
59
+ def test_children_of
60
+ unique_call_path = UniqueCallPath.new
61
+
62
+ result = RubyProf.profile do
63
+ unique_call_path.method_a(1)
64
+ unique_call_path.method_k(2)
65
+ end
66
+
67
+ root_call_info = result.threads.first.call_tree
68
+ assert_equal("UniqueCallPathTest#test_children_of", root_call_info.target.full_name)
69
+
70
+ call_info_a = root_call_info.children.detect do |call_tree|
71
+ call_tree.target.full_name == "UniqueCallPath#method_a"
72
+ end
73
+ refute_nil(call_info_a)
74
+
75
+ _children_of_a = call_info_a.children.inject(Array.new) do |array, c|
76
+ if c.parent.eql?(call_info_a)
77
+ array << c
78
+ end
79
+ array
80
+ end
81
+
82
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.1')
83
+ assert_equal(1, call_info_a.children.length)
84
+ assert_equal("UniqueCallPath#method_b", call_info_a.children[0].target.full_name)
85
+ else
86
+ assert_equal(2, call_info_a.children.length)
87
+ assert_equal("Integer#==", call_info_a.children[0].target.full_name)
88
+ assert_equal("UniqueCallPath#method_b", call_info_a.children[1].target.full_name)
89
+ end
90
+ end
91
+
92
+ def test_unique_path
93
+ unique_call_path = UniqueCallPath.new
94
+
95
+ result = RubyProf.profile do
96
+ unique_call_path.method_a(1)
97
+ unique_call_path.method_k(1)
98
+ end
99
+
100
+ root_call_info = result.threads.first.call_tree
101
+ assert_equal("UniqueCallPathTest#test_unique_path", root_call_info.target.full_name)
102
+
103
+ call_info_a = root_call_info.children.detect do |call_tree|
104
+ call_tree.target.full_name == "UniqueCallPath#method_a"
105
+ end
106
+ refute_nil(call_info_a)
107
+
108
+ children_of_a = call_info_a.children.reduce(Array.new) do |array, c|
109
+ if c.parent.eql?(call_info_a)
110
+ array << c
111
+ end
112
+ array
113
+ end
114
+
115
+ children_of_a = children_of_a.sort do |c1, c2|
116
+ c1.target.full_name <=> c2.target.full_name
117
+ end
118
+
119
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.1')
120
+ assert_equal(1, call_info_a.children.length)
121
+ assert_equal(1, children_of_a.length)
122
+
123
+ assert_equal(1, children_of_a[0].called)
124
+ assert_equal("UniqueCallPath#method_b", children_of_a[0].target.full_name)
125
+ else
126
+ assert_equal(2, call_info_a.children.length)
127
+ assert_equal(2, children_of_a.length)
128
+
129
+ assert_equal(1, children_of_a[0].called)
130
+ assert_equal("Integer#==", children_of_a[0].target.full_name)
131
+
132
+ assert_equal(1, children_of_a[1].called)
133
+ assert_equal("UniqueCallPath#method_b", children_of_a[1].target.full_name)
134
+ end
135
+ end
136
+ end
data/test/yarv_test.rb ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # tests for bugs reported by users
7
+ class YarvTest < TestCase
8
+ def setup
9
+ RubyProf::measure_mode = RubyProf::WALL_TIME
10
+ define_methods
11
+ end
12
+
13
+ def test_array_push_unoptimized
14
+ a = nil
15
+ result = RubyProf.profile do
16
+ a = self.array_push_unoptimized
17
+ end
18
+ assert_equal 2, a.length
19
+ assert_equal ["YarvTest#test_array_push_unoptimized", "YarvTest#array_push_unoptimized", 'Array#<<', "Array#push"], result.threads.first.methods.map(&:full_name)
20
+ end
21
+
22
+ def test_array_push_optimized
23
+ a = nil
24
+ result = RubyProf.profile do
25
+ a = self.array_push_optimized
26
+ end
27
+ assert_equal(2, a.length)
28
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.1')
29
+ assert_equal(["YarvTest#test_array_push_optimized", "YarvTest#array_push_optimized", "Array#push"], result.threads.first.methods.map(&:full_name))
30
+ else
31
+ assert_equal(["YarvTest#test_array_push_optimized", "YarvTest#array_push_optimized", "Array#<<", "Array#push"], result.threads.first.methods.map(&:full_name))
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def define_methods
38
+ return if respond_to?(:array_push_optimized)
39
+ old_compile_option = RubyVM::InstructionSequence.compile_option
40
+ RubyVM::InstructionSequence.compile_option = {
41
+ :trace_instruction => true,
42
+ :specialized_instruction => false
43
+ }
44
+ self.class.class_eval <<-"EOM"
45
+ def array_push_unoptimized
46
+ a = []
47
+ a << 1
48
+ a.push 2
49
+ end
50
+ EOM
51
+ RubyVM::InstructionSequence.compile_option = old_compile_option
52
+ self.class.class_eval <<-"EOM"
53
+ def array_push_optimized
54
+ a = []
55
+ a << 1
56
+ a.push 2
57
+ end
58
+ EOM
59
+ end
60
+ end