ruby-prof 0.4.1 → 0.5.0

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 (57) hide show
  1. data/CHANGES +30 -0
  2. data/README +65 -25
  3. data/Rakefile +33 -32
  4. data/bin/ruby-prof +100 -83
  5. data/examples/graph.html +65 -69
  6. data/ext/measure_allocations.h +43 -0
  7. data/ext/measure_cpu_time.h +138 -0
  8. data/ext/measure_process_time.h +41 -0
  9. data/ext/measure_wall_time.h +42 -0
  10. data/ext/ruby_prof.c +737 -653
  11. data/lib/ruby-prof.rb +41 -38
  12. data/lib/ruby-prof/abstract_printer.rb +42 -0
  13. data/lib/ruby-prof/call_tree_printer.rb +69 -0
  14. data/lib/ruby-prof/flat_printer.rb +78 -75
  15. data/lib/ruby-prof/graph_html_printer.rb +241 -228
  16. data/lib/ruby-prof/graph_printer.rb +160 -141
  17. data/lib/ruby-prof/profile_test_case.rb +80 -0
  18. data/lib/ruby-prof/rails_plugin/ruby-prof/init.rb +6 -0
  19. data/lib/ruby-prof/rails_plugin/ruby-prof/lib/profiling.rb +52 -0
  20. data/lib/ruby-prof/task.rb +147 -0
  21. data/test/basic_test.rb +65 -35
  22. data/test/duplicate_names_test.rb +20 -24
  23. data/test/gc.log +5 -0
  24. data/test/measure_mode_test.rb +79 -0
  25. data/test/module_test.rb +31 -18
  26. data/test/no_method_class_test.rb +14 -0
  27. data/test/prime1.rb +17 -0
  28. data/test/prime2.rb +26 -0
  29. data/test/prime3.rb +17 -0
  30. data/test/prime_test.rb +10 -10
  31. data/test/printers_test.rb +14 -12
  32. data/test/profile_unit_test.rb +24 -0
  33. data/test/recursive_test.rb +105 -17
  34. data/test/singleton_test.rb +38 -0
  35. data/test/start_test.rb +24 -0
  36. data/test/test_helper.rb +33 -29
  37. data/test/test_suite.rb +10 -2
  38. data/test/thread_test.rb +123 -17
  39. data/test/timing_test.rb +70 -29
  40. metadata +28 -30
  41. data/doc/created.rid +0 -1
  42. data/doc/files/LICENSE.html +0 -0
  43. data/doc/files/README.html +0 -376
  44. data/doc/files/bin/ruby-prof.html +0 -143
  45. data/doc/files/examples/flat_txt.html +0 -179
  46. data/doc/files/examples/graph_html.html +0 -948
  47. data/doc/files/examples/graph_txt.html +0 -297
  48. data/doc/files/ext/ruby_prof_c.html +0 -101
  49. data/doc/files/lib/ruby-prof/flat_printer_rb.html +0 -101
  50. data/doc/files/lib/ruby-prof/graph_html_printer_rb.html +0 -108
  51. data/doc/files/lib/ruby-prof/graph_printer_rb.html +0 -101
  52. data/doc/files/lib/ruby-prof/profiletask_rb.html +0 -109
  53. data/doc/files/lib/ruby-prof_rb.html +0 -111
  54. data/doc/files/lib/unprof_rb.html +0 -108
  55. data/doc/rdoc-style.css +0 -208
  56. data/lib/ruby-prof/profiletask.rb +0 -150
  57. data/test/clock_mode_test.rb +0 -73
@@ -4,16 +4,22 @@ require 'test/unit'
4
4
  require 'ruby-prof'
5
5
  require 'test_helper'
6
6
 
7
+ # Need to use wall time for this test due to the sleep calls
8
+ RubyProf::measure_mode = RubyProf::WALL_TIME
9
+
7
10
  class C1
8
11
  def C1.hello
12
+ sleep(0.1)
9
13
  end
10
14
 
11
15
  def hello
16
+ sleep(0.2)
12
17
  end
13
18
  end
14
19
 
15
20
  module M1
16
21
  def hello
22
+ sleep(0.3)
17
23
  end
18
24
  end
19
25
 
@@ -24,11 +30,13 @@ end
24
30
 
25
31
  class C3
26
32
  def hello
33
+ sleep(0.4)
27
34
  end
28
35
  end
29
36
 
30
37
  module M4
31
38
  def hello
39
+ sleep(0.5)
32
40
  end
33
41
  end
34
42
 
@@ -58,7 +66,7 @@ class BasicTest < Test::Unit::TestCase
58
66
  def test_double_profile
59
67
  RubyProf.start
60
68
  assert_raise(RuntimeError) do
61
- RubyProf.start
69
+ RubyProf.start
62
70
  end
63
71
 
64
72
  assert_raise(RuntimeError) do
@@ -71,68 +79,79 @@ class BasicTest < Test::Unit::TestCase
71
79
 
72
80
  def test_no_block
73
81
  assert_raise(ArgumentError) do
74
- RubyProf.profile
75
- end
82
+ RubyProf.profile
83
+ end
76
84
  end
77
85
 
78
86
  def test_class_and_instance_methods
79
87
  result = RubyProf.profile do
80
- C1.hello
81
- C1.new.hello
88
+ C1.hello
89
+ C1.new.hello
82
90
  end
83
-
91
+
84
92
  methods = result.threads.values.first
85
93
 
86
94
  # Length should be 6:
87
- # 1 top level,
88
- # 1 Class.new
89
- # 1 Class:Object allocate
95
+ # 1 test_class_and_instance_methods (this method)
96
+ # 1 Class.new
97
+ # 1 Class:Object allocate
90
98
  # 1 for Object.initialize
91
99
  # 1 for Class hello
92
100
  # 1 for Object hello
93
- assert_equal(6, methods.length)
101
+ # 1 sleep
102
+ assert_equal(7, methods.length)
94
103
 
95
- # Check class method
96
- method1 = methods['<Class::C1>#hello']
97
- assert_not_nil(method1)
104
+ # Check the names
105
+ methods = methods.sort.reverse
98
106
 
99
- # Check instance method
100
- method1 = methods['C1#hello']
101
- assert_not_nil(method1)
107
+ assert_equal('BasicTest#test_class_and_instance_methods', methods[0].full_name)
108
+ assert_equal('Kernel#sleep', methods[1].full_name)
109
+ assert_equal('C1#hello', methods[2].full_name)
110
+ assert_equal('<Class::C1>#hello', methods[3].full_name)
111
+ assert_equal('Class#new', methods[4].full_name)
112
+ assert_equal('<Class::Object>#allocate', methods[5].full_name)
113
+ assert_equal('Object#initialize', methods[6].full_name)
102
114
  end
103
115
 
104
116
  def test_module_methods
105
117
  result = RubyProf.profile do
106
- C2.hello
107
- C2.new.hello
118
+ C2.hello
119
+ C2.new.hello
108
120
  end
109
121
 
110
122
  methods = result.threads.values.first
111
123
 
112
- # Length should be 5:
113
- # 1 top level,
114
- # 1 Class.new
115
- # 1 Class:Object allocate
116
- # 1 for Object.initialize
117
- # 1 for hello
118
- assert_equal(5, methods.length)
124
+ # Length should be 6:
125
+ # 1 BasicTest#test_module_methods (this method)
126
+ # 1 Class#new
127
+ # 1 <Class::Object>#allocate
128
+ # 1 Object#initialize
129
+ # 1 M1#hello
130
+ # 1 Kernel#sleep
131
+
132
+ assert_equal(6, methods.length)
133
+
134
+ # Check the names
135
+ methods = methods.sort.reverse
119
136
 
120
- # Check class method
121
- method1 = methods['M1#hello']
122
- assert_not_nil(method1)
123
- assert_equal(2, method1.called)
137
+ assert_equal('BasicTest#test_module_methods', methods[0].full_name)
138
+ assert_equal('M1#hello', methods[1].full_name)
139
+ assert_equal('Kernel#sleep', methods[2].full_name)
140
+ assert_equal('Class#new', methods[3].full_name)
141
+ assert_equal('<Class::Object>#allocate', methods[4].full_name)
142
+ assert_equal('Object#initialize', methods[5].full_name)
124
143
  end
125
144
 
126
145
  def test_singleton
127
146
  c3 = C3.new
128
147
 
129
148
  class << c3
130
- def hello
131
- end
132
- end
149
+ def hello
150
+ end
151
+ end
133
152
 
134
153
  result = RubyProf.profile do
135
- c3.hello
154
+ c3.hello
136
155
  end
137
156
 
138
157
  methods = result.threads.values.first
@@ -142,7 +161,18 @@ class BasicTest < Test::Unit::TestCase
142
161
  assert_equal(2, methods.length)
143
162
 
144
163
  # Check singleton method
145
- method1 = methods['<Object::C3>#hello']
146
- assert_not_nil(method1)
164
+ methods = methods.sort.reverse
165
+
166
+ assert_equal('BasicTest#test_singleton', methods[0].full_name)
167
+ assert_equal('<Object::C3>#hello', methods[1].full_name)
147
168
  end
169
+
170
+ def test_traceback
171
+ RubyProf.start
172
+ assert_raise(NoMethodError) do
173
+ RubyProf.xxx
174
+ end
175
+
176
+ RubyProf.stop
177
+ end
148
178
  end
@@ -7,31 +7,27 @@ require 'test_helper'
7
7
  class DuplicateNames < Test::Unit::TestCase
8
8
  def test_names
9
9
  result = RubyProf::profile do
10
- str = %{module Foo; class Bar; def foo; end end end}
10
+ str = %{module Foo; class Bar; def foo; end end end}
11
11
 
12
- eval str
13
- Foo::Bar.new.foo
14
- DuplicateNames.class_eval {remove_const :Foo}
12
+ eval str
13
+ Foo::Bar.new.foo
14
+ DuplicateNames.class_eval {remove_const :Foo}
15
15
 
16
- eval str
17
- Foo::Bar.new.foo
18
- DuplicateNames.class_eval {remove_const :Foo}
16
+ eval str
17
+ Foo::Bar.new.foo
18
+ DuplicateNames.class_eval {remove_const :Foo}
19
19
 
20
- eval str
21
- Foo::Bar.new.foo
22
- end
23
- print_results(result)
24
-
25
- # There should be 3 foo methods
26
- methods = result.threads.values.first
27
-
28
- method_info = methods['DuplicateNames::Foo::Bar#foo']
29
- assert_not_nil(method_info)
30
-
31
- method_info = methods['DuplicateNames::Foo::Bar#foo_1']
32
- assert_not_nil(method_info)
33
-
34
- method_info = methods['DuplicateNames::Foo::Bar#foo_2']
35
- assert_not_nil(method_info)
36
- end
20
+ eval str
21
+ Foo::Bar.new.foo
22
+ end
23
+
24
+ # There should be 3 foo methods
25
+ methods = result.threads.values.first
26
+
27
+ methods = methods.select do |method|
28
+ method.full_name == 'DuplicateNames::Foo::Bar#foo'
29
+ end
30
+
31
+ assert_equal(3, methods.length)
32
+ end
37
33
  end
@@ -0,0 +1,5 @@
1
+ GC Warning: Finalization cycle involving 99c25f0
2
+ GC Warning: Finalization cycle involving 99c25f0
3
+ GC Warning: Finalization cycle involving 99c25f0
4
+ GC Warning: Finalization cycle involving 99c25f0
5
+ GC Warning: Finalization cycle involving 99c25f0
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+ require 'prime'
7
+
8
+
9
+ # -- Tests ----
10
+ class MeasureModeTest < Test::Unit::TestCase
11
+
12
+ def test_process_time
13
+ RubyProf::measure_mode = RubyProf::PROCESS_TIME
14
+ assert_equal(RubyProf::PROCESS_TIME, RubyProf::measure_mode)
15
+ result = RubyProf.profile do
16
+ run_primes
17
+ end
18
+
19
+ result.threads.each do |thread_id, methods|
20
+ methods.each do |method|
21
+ check_parent_times(method)
22
+ check_parent_calls(method)
23
+ check_child_times(method)
24
+ end
25
+ end
26
+ end
27
+
28
+ def test_wall_time
29
+ RubyProf::measure_mode = RubyProf::WALL_TIME
30
+ assert_equal(RubyProf::WALL_TIME, RubyProf::measure_mode)
31
+ result = RubyProf.profile do
32
+ run_primes
33
+ end
34
+
35
+ result.threads.values.each do |methods|
36
+ methods.each do |method|
37
+ check_parent_times(method)
38
+ check_parent_calls(method)
39
+ check_child_times(method)
40
+ end
41
+ end
42
+ end
43
+
44
+ def test_cpu
45
+ return unless RubyProf.constants.include?('CPU_TIME')
46
+
47
+ RubyProf::measure_mode = RubyProf::CPU_TIME
48
+ assert_equal(RubyProf::CPU_TIME, RubyProf::measure_mode)
49
+ result = RubyProf.profile do
50
+ run_primes
51
+ end
52
+
53
+ result.threads.values.each do |methods|
54
+ methods.each do |method|
55
+ check_parent_times(method)
56
+ check_parent_calls(method)
57
+ check_child_times(method)
58
+ end
59
+ end
60
+ end
61
+
62
+ def test_allocated_objects
63
+ return unless RubyProf.constants.include?('ALLOCATIONS')
64
+
65
+ RubyProf::measure_mode = RubyProf::ALLOCATIONS
66
+
67
+ assert_equal(RubyProf::ALLOCATIONS, RubyProf::measure_mode)
68
+
69
+ result = RubyProf.profile do
70
+ Array.new
71
+ end
72
+ end
73
+
74
+ def test_invalid
75
+ assert_raise(ArgumentError) do
76
+ RubyProf::measure_mode = 7777
77
+ end
78
+ end
79
+ end
@@ -4,42 +4,55 @@ require 'test/unit'
4
4
  require 'ruby-prof'
5
5
  require 'test_helper'
6
6
 
7
+ # Need to use wall time for this test due to the sleep calls
8
+ RubyProf::measure_mode = RubyProf::WALL_TIME
9
+
7
10
 
8
11
  module Foo
9
12
  def Foo::hello
13
+ sleep(0.5)
10
14
  end
11
15
  end
12
16
 
13
17
  module Bar
14
18
  def Bar::hello
19
+ sleep(0.5)
15
20
  Foo::hello
16
21
  end
17
22
 
18
23
  def hello
24
+ sleep(0.5)
19
25
  Bar::hello
20
26
  end
21
27
  end
22
28
 
23
29
  include Bar
24
30
 
25
- class BasicTest < Test::Unit::TestCase
31
+ class ModuleTest < Test::Unit::TestCase
26
32
  def test_nested_modules
27
- result = RubyProf.profile do
28
- hello
29
- end
30
-
31
- methods = result.threads.values.first
32
-
33
- # Length should be 4s
34
- assert_equal(4, methods.length)
33
+ result = RubyProf.profile do
34
+ hello
35
+ end
36
+
37
+ methods = result.threads.values.first
38
+ methods = methods.sort.reverse
39
+
40
+ # Length should be 4
41
+ assert_equal(5, methods.length)
42
+
43
+ method = methods[0]
44
+ assert_equal('ModuleTest#test_nested_modules', method.full_name)
45
+
46
+ method = methods[1]
47
+ assert_equal('Bar#hello', method.full_name)
48
+
49
+ method = methods[2]
50
+ assert_equal('Kernel#sleep', method.full_name)
51
+
52
+ method = methods[3]
53
+ assert_equal('<Module::Bar>#hello', method.full_name)
35
54
 
36
- method1 = methods['Bar#hello']
37
- assert_not_nil(method1)
38
-
39
- method1 = methods['<Module::Bar>#hello']
40
- assert_not_nil(method1)
41
-
42
- method1 = methods['<Module::Foo>#hello']
43
- assert_not_nil(method1)
44
- end
55
+ method = methods[4]
56
+ assert_equal('<Module::Foo>#hello', method.full_name)
57
+ end
45
58
  end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ruby-prof'
4
+
5
+ # Make sure this works with no class or method
6
+ result = RubyProf.profile do
7
+ sleep 1
8
+ end
9
+
10
+ method = result.threads.values.first.sort.last
11
+
12
+ if method.full_name != 'Global#[No method]'
13
+ raise(RuntimeError, "Wrong method name. Expected: Global#[No method]. Actual: #{method.full_name}")
14
+ end
@@ -0,0 +1,17 @@
1
+ require 'prime2'
2
+ require 'prime3'
3
+
4
+ def run_primes
5
+ length = 500
6
+ maxnum = 10000
7
+
8
+ # Create random numbers
9
+ random_array = make_random_array(length, maxnum)
10
+
11
+ # Find the primes
12
+ primes = find_primes(random_array)
13
+
14
+ # Find the largest primes
15
+ largest = find_largest(primes)
16
+ #puts "largest is #{largest}"
17
+ end
@@ -0,0 +1,26 @@
1
+ require 'prime3'
2
+
3
+ # Need to use wall time for this test due to the sleep calls
4
+ RubyProf::measure_mode = RubyProf::WALL_TIME
5
+
6
+ def find_primes(arr)
7
+ result = arr.select do |value|
8
+ is_prime(value)
9
+ end
10
+ result
11
+ end
12
+
13
+ def find_largest(primes)
14
+ largest = primes.first
15
+
16
+ # Intentionally use upto for example purposes
17
+ # (upto is also called from is_prime)
18
+ 0.upto(primes.length-1) do |i|
19
+ sleep(0.02)
20
+ prime = primes[i]
21
+ if prime > largest
22
+ largest = prime
23
+ end
24
+ end
25
+ largest
26
+ end