ruby-prof 0.18.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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +500 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +487 -0
  5. data/Rakefile +113 -0
  6. data/bin/ruby-prof +345 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/examples/flat.txt +50 -0
  9. data/examples/graph.dot +84 -0
  10. data/examples/graph.html +823 -0
  11. data/examples/graph.txt +139 -0
  12. data/examples/multi.flat.txt +23 -0
  13. data/examples/multi.graph.html +760 -0
  14. data/examples/multi.grind.dat +114 -0
  15. data/examples/multi.stack.html +547 -0
  16. data/examples/stack.html +547 -0
  17. data/ext/ruby_prof/extconf.rb +68 -0
  18. data/ext/ruby_prof/rp_call_info.c +425 -0
  19. data/ext/ruby_prof/rp_call_info.h +53 -0
  20. data/ext/ruby_prof/rp_measure.c +40 -0
  21. data/ext/ruby_prof/rp_measure.h +45 -0
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -0
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -0
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -0
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -0
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -0
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -0
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -0
  29. data/ext/ruby_prof/rp_method.c +630 -0
  30. data/ext/ruby_prof/rp_method.h +75 -0
  31. data/ext/ruby_prof/rp_stack.c +173 -0
  32. data/ext/ruby_prof/rp_stack.h +63 -0
  33. data/ext/ruby_prof/rp_thread.c +277 -0
  34. data/ext/ruby_prof/rp_thread.h +27 -0
  35. data/ext/ruby_prof/ruby_prof.c +794 -0
  36. data/ext/ruby_prof/ruby_prof.h +60 -0
  37. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  38. data/ext/ruby_prof/vc/ruby_prof.vcxproj +141 -0
  39. data/lib/2.6.3/ruby_prof.so +0 -0
  40. data/lib/ruby-prof.rb +68 -0
  41. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  42. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  43. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  45. data/lib/ruby-prof/call_info.rb +115 -0
  46. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  47. data/lib/ruby-prof/compatibility.rb +179 -0
  48. data/lib/ruby-prof/method_info.rb +121 -0
  49. data/lib/ruby-prof/printers/abstract_printer.rb +104 -0
  50. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  51. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -0
  52. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -0
  53. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  54. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  55. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -0
  56. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -0
  57. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  58. data/lib/ruby-prof/printers/multi_printer.rb +84 -0
  59. data/lib/ruby-prof/profile.rb +26 -0
  60. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -0
  61. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -0
  62. data/lib/ruby-prof/rack.rb +174 -0
  63. data/lib/ruby-prof/task.rb +147 -0
  64. data/lib/ruby-prof/thread.rb +35 -0
  65. data/lib/ruby-prof/version.rb +3 -0
  66. data/lib/unprof.rb +10 -0
  67. data/ruby-prof.gemspec +58 -0
  68. data/test/abstract_printer_test.rb +53 -0
  69. data/test/aggregate_test.rb +136 -0
  70. data/test/basic_test.rb +128 -0
  71. data/test/block_test.rb +74 -0
  72. data/test/call_info_test.rb +78 -0
  73. data/test/call_info_visitor_test.rb +31 -0
  74. data/test/duplicate_names_test.rb +32 -0
  75. data/test/dynamic_method_test.rb +55 -0
  76. data/test/enumerable_test.rb +21 -0
  77. data/test/exceptions_test.rb +24 -0
  78. data/test/exclude_methods_test.rb +146 -0
  79. data/test/exclude_threads_test.rb +53 -0
  80. data/test/fiber_test.rb +79 -0
  81. data/test/issue137_test.rb +63 -0
  82. data/test/line_number_test.rb +80 -0
  83. data/test/measure_allocations_test.rb +26 -0
  84. data/test/measure_cpu_time_test.rb +212 -0
  85. data/test/measure_gc_runs_test.rb +32 -0
  86. data/test/measure_gc_time_test.rb +36 -0
  87. data/test/measure_memory_test.rb +33 -0
  88. data/test/measure_process_time_test.rb +61 -0
  89. data/test/measure_wall_time_test.rb +255 -0
  90. data/test/method_elimination_test.rb +84 -0
  91. data/test/module_test.rb +45 -0
  92. data/test/multi_printer_test.rb +104 -0
  93. data/test/no_method_class_test.rb +15 -0
  94. data/test/pause_resume_test.rb +166 -0
  95. data/test/prime.rb +54 -0
  96. data/test/printers_test.rb +275 -0
  97. data/test/printing_recursive_graph_test.rb +127 -0
  98. data/test/rack_test.rb +157 -0
  99. data/test/recursive_test.rb +215 -0
  100. data/test/singleton_test.rb +38 -0
  101. data/test/stack_printer_test.rb +77 -0
  102. data/test/stack_test.rb +138 -0
  103. data/test/start_stop_test.rb +112 -0
  104. data/test/test_helper.rb +267 -0
  105. data/test/thread_test.rb +187 -0
  106. data/test/unique_call_path_test.rb +202 -0
  107. data/test/yarv_test.rb +55 -0
  108. metadata +199 -0
@@ -0,0 +1,84 @@
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
+ module MethodElimination
14
+ def self.a
15
+ 1.times {|i| c}
16
+ end
17
+
18
+ def self.b
19
+ sleep 0.1
20
+ end
21
+
22
+ def self.c
23
+ 1.times {|i| b}
24
+ end
25
+ end
26
+
27
+ class MethodEliminationTest < TestCase
28
+ def setup
29
+ # Need to use wall time for this test due to the sleep calls
30
+ RubyProf::measure_mode = RubyProf::WALL_TIME
31
+ end
32
+
33
+ def test_setting_parent
34
+ result = RubyProf.profile do
35
+ 1000.times { 1+1 }
36
+ end
37
+ method_infos = result.threads.first.methods.sort.reverse
38
+ assert(m1 = method_infos[0])
39
+ assert(c1 = m1.call_infos.first)
40
+ assert_nil(c1.parent)
41
+ end
42
+
43
+ def test_methods_can_be_eliminated
44
+ RubyProf.start
45
+ 5.times {MethodElimination.a}
46
+ result = RubyProf.stop
47
+
48
+ methods = result.threads.first.methods.sort.reverse
49
+
50
+ assert_equal(6, methods.count)
51
+ assert_equal('MethodEliminationTest#test_methods_can_be_eliminated', methods[0].full_name)
52
+ assert_equal('Integer#times', methods[1].full_name)
53
+ assert_equal('<Module::MethodElimination>#a', methods[2].full_name)
54
+ assert_equal('<Module::MethodElimination>#c', methods[3].full_name)
55
+ assert_equal('<Module::MethodElimination>#b', methods[4].full_name)
56
+ assert_equal('Kernel#sleep', methods[5].full_name)
57
+
58
+ result.eliminate_methods!([/Integer#times/])
59
+
60
+ methods = result.threads.first.methods.sort.reverse
61
+ assert_equal(5, methods.count)
62
+ assert_equal('MethodEliminationTest#test_methods_can_be_eliminated', methods[0].full_name)
63
+ assert_equal('<Module::MethodElimination>#a', methods[1].full_name)
64
+ assert_equal('<Module::MethodElimination>#c', methods[2].full_name)
65
+ assert_equal('<Module::MethodElimination>#b', methods[3].full_name)
66
+ assert_equal('Kernel#sleep', methods[4].full_name)
67
+ end
68
+
69
+ private
70
+
71
+ def assert_method_has_been_eliminated(result, eliminated_method)
72
+ result.threads.each do |thread|
73
+ thread.methods.each do |method|
74
+ method.call_infos.each do |ci|
75
+ assert(ci.target != eliminated_method, "broken self")
76
+ assert(ci.parent.target != eliminated_method, "broken parent") if ci.parent
77
+ ci.children.each do |callee|
78
+ assert(callee.target != eliminated_method, "broken kid")
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Need to use wall time for this test due to the sleep calls
7
+ RubyProf::measure_mode = RubyProf::WALL_TIME
8
+
9
+ module Foo
10
+ def Foo::hello
11
+ sleep(0.5)
12
+ end
13
+ end
14
+
15
+ module Bar
16
+ def Bar::hello
17
+ sleep(0.5)
18
+ Foo::hello
19
+ end
20
+
21
+ def hello
22
+ sleep(0.5)
23
+ Bar::hello
24
+ end
25
+ end
26
+
27
+ include Bar
28
+
29
+ class ModuleTest < TestCase
30
+ def test_nested_modules
31
+ result = RubyProf.profile do
32
+ hello
33
+ end
34
+
35
+ methods = result.threads.first.methods
36
+
37
+ # Length should be 5
38
+ assert_equal(5, methods.length)
39
+
40
+ # these methods should be in there... (hard to tell order though).
41
+ for name in ['ModuleTest#test_nested_modules','Bar#hello','Kernel#sleep','<Module::Bar>#hello','<Module::Foo>#hello']
42
+ assert methods.map(&:full_name).include?( name )
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,104 @@
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 MSTPT
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 MultiPrinterTest < 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_refuses_io_objects
36
+ # we don't need a real profile for this test
37
+ p = RubyProf::MultiPrinter.new nil
38
+ begin
39
+ p.print(STDOUT)
40
+ flunk "should have raised an ArgumentError"
41
+ rescue ArgumentError => e
42
+ assert_match(/IO/, e.to_s)
43
+ end
44
+ end
45
+
46
+ def test_refuses_non_hashes
47
+ # we don't need a real profile for this test
48
+ p = RubyProf::MultiPrinter.new nil
49
+ begin
50
+ p.print([])
51
+ flunk "should have raised an ArgumentError"
52
+ rescue ArgumentError => e
53
+ assert_match(/hash/, e.to_s)
54
+ end
55
+ end
56
+
57
+ def test_all_profiles_can_be_created
58
+ start_time = Time.now
59
+ RubyProf.start
60
+ 5.times{MSTPT.new.a}
61
+ result = RubyProf.stop
62
+ end_time = Time.now
63
+ expected_time = end_time - start_time
64
+ graph = print(result)[1]
65
+ re = Regexp.new('
66
+ \s*<table>
67
+ \s*<tr>
68
+ \s*<th>Thread ID</th>
69
+ \s*(<th>Fiber ID</th>)?
70
+ \s*<th>Total Time</th>
71
+ \s*</tr>
72
+ \s*
73
+ \s*<tr>
74
+ \s*(<td>([\.0-9]+)</td>)?
75
+ \s*<td><a href="#-?\d+">-?\d+</a></td>
76
+ \s*<td>([\.0-9e]+)</td>
77
+ \s*</tr>
78
+ \s*
79
+ \s*</table>')
80
+ assert_match(re, graph)
81
+ graph =~ re
82
+ display_time = $4.to_f
83
+ assert_in_delta expected_time, display_time, 0.001
84
+ end
85
+
86
+ private
87
+
88
+ def print(result)
89
+ test = caller.first =~ /in `(.*)'/ ? $1 : "test"
90
+ path = RubyProf.tmpdir
91
+ profile = "ruby_prof_#{test}"
92
+ printer = RubyProf::MultiPrinter.new(result)
93
+ printer.print(:path => path, :profile => profile,
94
+ :threshold => 0, :min_percent => 0, :title => "ruby_prof #{test}")
95
+ if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
96
+ system("open '#{printer.stack_profile}'")
97
+ end
98
+ # if GC.respond_to?(:dump_file_and_line_info)
99
+ # GC.start
100
+ # GC.dump_file_and_line_info("heap.dump")
101
+ # end
102
+ [File.read(printer.stack_profile), File.read(printer.graph_profile)]
103
+ end
104
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Make sure this works with no class or method
7
+ result = RubyProf.profile do
8
+ sleep 1
9
+ end
10
+
11
+ methods = result.threads.first.methods
12
+ global_method = methods.sort_by {|method| method.full_name}.first
13
+ if global_method.full_name != 'Kernel#sleep'
14
+ raise(RuntimeError, "Wrong method name. Expected: Global#[No method]. Actual: #{global_method.full_name}")
15
+ end
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class PauseResumeTest < 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 test_pause_resume
13
+ # Measured
14
+ RubyProf.start
15
+ RubyProf::C1.hello
16
+
17
+ # Not measured
18
+ RubyProf.pause
19
+ sleep 1
20
+ RubyProf::C1.hello
21
+
22
+ # Measured
23
+ RubyProf.resume
24
+ RubyProf::C1.hello
25
+
26
+ result = RubyProf.stop
27
+
28
+ # Length should be 3:
29
+ # PauseResumeTest#test_pause_resume
30
+ # <Class::RubyProf::C1>#hello
31
+ # Kernel#sleep
32
+
33
+ methods = result.threads.first.methods.sort_by {|method_info| method_info.full_name}
34
+ # remove methods called by pause/resume
35
+ called_methods = ['Array#include?', 'Fixnum#==', 'Kernel#respond_to?', 'Kernel#respond_to_missing?']
36
+ methods.reject!{|m| called_methods.include?(m.full_name) }
37
+ # TODO: fix pause/resume to not include those methods in the first place
38
+ assert_equal(3, methods.length)
39
+
40
+ # Check the names
41
+ assert_equal('<Class::RubyProf::C1>#hello', methods[0].full_name)
42
+ assert_equal('Kernel#sleep', methods[1].full_name)
43
+ assert_equal('PauseResumeTest#test_pause_resume', methods[2].full_name)
44
+
45
+ # Check times
46
+ assert_in_delta(0.2, methods[0].total_time, 0.02)
47
+ assert_in_delta(0, methods[0].wait_time, 0.02)
48
+ assert_in_delta(0, methods[0].self_time, 0.02)
49
+
50
+ assert_in_delta(0.2, methods[1].total_time, 0.02)
51
+ assert_in_delta(0, methods[1].wait_time, 0.02)
52
+ assert_in_delta(0.2, methods[1].self_time, 0.02)
53
+
54
+ assert_in_delta(0.2, methods[2].total_time, 0.02)
55
+ assert_in_delta(0, methods[2].wait_time, 0.02)
56
+ assert_in_delta(0, methods[2].self_time, 0.02)
57
+ end
58
+
59
+ # pause/resume in the same frame
60
+ def test_pause_resume_1
61
+ profile = RubyProf::Profile.new
62
+
63
+ profile.start
64
+ method_1a
65
+
66
+ profile.pause
67
+ method_1b
68
+
69
+ profile.resume
70
+ method_1c
71
+
72
+ result = profile.stop
73
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05)
74
+ end
75
+ def method_1a; sleep 0.2 end
76
+ def method_1b; sleep 1 end
77
+ def method_1c; sleep 0.4 end
78
+
79
+ # pause in parent frame, resume in child
80
+ def test_pause_resume_2
81
+ profile = RubyProf::Profile.new
82
+
83
+ profile.start
84
+ method_2a
85
+
86
+ profile.pause
87
+ sleep 0.5
88
+ method_2b(profile)
89
+
90
+ result = profile.stop
91
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05)
92
+ end
93
+ def method_2a; sleep 0.2 end
94
+ def method_2b(profile); sleep 0.5; profile.resume; sleep 0.4 end
95
+
96
+ # pause in child frame, resume in parent
97
+ def test_pause_resume_3
98
+ profile = RubyProf::Profile.new
99
+
100
+ profile.start
101
+ method_3a(profile)
102
+
103
+ sleep 0.5
104
+ profile.resume
105
+ method_3b
106
+
107
+ result = profile.stop
108
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05)
109
+ end
110
+ def method_3a(profile); sleep 0.2; profile.pause; sleep 0.5 end
111
+ def method_3b; sleep 0.4 end
112
+
113
+ def test_pause_seq
114
+ profile = RubyProf::Profile.new
115
+ profile.start ; assert !profile.paused?
116
+ profile.pause ; assert profile.paused?
117
+ profile.resume; assert !profile.paused?
118
+ profile.pause ; assert profile.paused?
119
+ profile.pause ; assert profile.paused?
120
+ profile.resume; assert !profile.paused?
121
+ profile.resume; assert !profile.paused?
122
+ profile.stop ; assert !profile.paused?
123
+ end
124
+
125
+ def test_pause_block
126
+ profile = RubyProf::Profile.new
127
+ profile.start
128
+ profile.pause
129
+ assert profile.paused?
130
+
131
+ times_block_invoked = 0
132
+ retval= profile.resume{
133
+ times_block_invoked += 1
134
+ 120 + times_block_invoked
135
+ }
136
+ assert_equal 1, times_block_invoked
137
+ assert profile.paused?
138
+
139
+ assert_equal 121, retval, "resume() should return the result of the given block."
140
+
141
+ profile.stop
142
+ end
143
+
144
+ def test_pause_block_with_error
145
+ profile = RubyProf::Profile.new
146
+ profile.start
147
+ profile.pause
148
+ assert profile.paused?
149
+
150
+ begin
151
+ profile.resume{ raise }
152
+ flunk 'Exception expected.'
153
+ rescue
154
+ assert profile.paused?
155
+ end
156
+
157
+ profile.stop
158
+ end
159
+
160
+ def test_resume_when_not_paused
161
+ profile = RubyProf::Profile.new
162
+ profile.start ; assert !profile.paused?
163
+ profile.resume; assert !profile.paused?
164
+ profile.stop ; assert !profile.paused?
165
+ end
166
+ end
data/test/prime.rb ADDED
@@ -0,0 +1,54 @@
1
+ # A silly little test program that finds prime numbers. It
2
+ # is intentionally badly designed to show off the use
3
+ # of ruby-prof.
4
+ #
5
+ # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
+
7
+ def make_random_array(length, maxnum)
8
+ result = Array.new(length)
9
+ result.each_index do |i|
10
+ result[i] = rand(maxnum)
11
+ end
12
+
13
+ result
14
+ end
15
+
16
+ def is_prime(x)
17
+ y = 2
18
+ y.upto(x-1) do |i|
19
+ return false if (x % i) == 0
20
+ end
21
+ true
22
+ end
23
+
24
+ def find_primes(arr)
25
+ result = arr.select do |value|
26
+ is_prime(value)
27
+ end
28
+ result
29
+ end
30
+
31
+ def find_largest(primes)
32
+ largest = primes.first
33
+
34
+ # Intentionally use upto for example purposes
35
+ # (upto is also called from is_prime)
36
+ 0.upto(primes.length-1) do |i|
37
+ prime = primes[i]
38
+ if prime > largest
39
+ largest = prime
40
+ end
41
+ end
42
+ largest
43
+ end
44
+
45
+ def run_primes(length=10, maxnum=1000)
46
+ # Create random numbers
47
+ random_array = make_random_array(length, maxnum)
48
+
49
+ # Find the primes
50
+ primes = find_primes(random_array)
51
+
52
+ # Find the largest primes
53
+ find_largest(primes)
54
+ end