ruby-prof 0.11.3 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGES +27 -0
  2. data/README.rdoc +14 -14
  3. data/bin/ruby-prof +275 -266
  4. data/ext/ruby_prof/rp_call_info.c +33 -24
  5. data/ext/ruby_prof/rp_call_info.h +2 -1
  6. data/ext/ruby_prof/rp_measure.c +1 -1
  7. data/ext/ruby_prof/rp_measure.h +1 -1
  8. data/ext/ruby_prof/rp_measure_allocations.c +1 -1
  9. data/ext/ruby_prof/rp_measure_cpu_time.c +1 -1
  10. data/ext/ruby_prof/rp_measure_gc_runs.c +1 -1
  11. data/ext/ruby_prof/rp_measure_gc_time.c +1 -1
  12. data/ext/ruby_prof/rp_measure_memory.c +1 -1
  13. data/ext/ruby_prof/rp_measure_process_time.c +2 -2
  14. data/ext/ruby_prof/rp_measure_wall_time.c +2 -2
  15. data/ext/ruby_prof/rp_method.c +11 -24
  16. data/ext/ruby_prof/rp_method.h +2 -3
  17. data/ext/ruby_prof/rp_stack.c +48 -7
  18. data/ext/ruby_prof/rp_stack.h +3 -3
  19. data/ext/ruby_prof/rp_thread.c +26 -17
  20. data/ext/ruby_prof/rp_thread.h +3 -3
  21. data/ext/ruby_prof/ruby_prof.c +7 -86
  22. data/ext/ruby_prof/ruby_prof.h +1 -1
  23. data/ext/ruby_prof/vc/ruby_prof.sln +12 -6
  24. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +110 -0
  25. data/ext/ruby_prof/vc/{ruby_prof.vcxproj → ruby_prof_19.vcxproj} +4 -1
  26. data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +112 -0
  27. data/ext/ruby_prof/version.h +4 -4
  28. data/lib/ruby-prof.rb +1 -0
  29. data/lib/ruby-prof/call_info.rb +1 -1
  30. data/lib/ruby-prof/call_info_visitor.rb +4 -2
  31. data/lib/ruby-prof/compatibility.rb +6 -1
  32. data/lib/ruby-prof/method_info.rb +1 -1
  33. data/lib/ruby-prof/printers/call_info_printer.rb +1 -1
  34. data/lib/ruby-prof/printers/call_stack_printer.rb +3 -3
  35. data/lib/ruby-prof/printers/dot_printer.rb +1 -1
  36. data/lib/ruby-prof/printers/flat_printer.rb +4 -4
  37. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +2 -2
  38. data/lib/ruby-prof/printers/graph_html_printer.rb +3 -3
  39. data/lib/ruby-prof/printers/graph_printer.rb +15 -15
  40. data/lib/ruby-prof/thread.rb +22 -0
  41. data/ruby-prof.gemspec +2 -1
  42. data/test/basic_test.rb +77 -45
  43. data/test/call_info_test.rb +78 -0
  44. data/test/call_info_visitor_test.rb +1 -1
  45. data/test/dynamic_method_test.rb +14 -8
  46. data/test/measure_cpu_time_test.rb +23 -12
  47. data/test/measure_process_time_test.rb +21 -170
  48. data/test/measure_wall_time_test.rb +59 -13
  49. data/test/method_elimination_test.rb +30 -19
  50. data/test/pause_resume_test.rb +129 -22
  51. data/test/prime.rb +0 -1
  52. data/test/printers_test.rb +7 -18
  53. data/test/recursive_test.rb +4 -48
  54. data/test/test_helper.rb +30 -10
  55. data/test/test_suite.rb +1 -2
  56. metadata +23 -5
  57. data/test/pause_test.rb +0 -57
  58. data/test/prime_test.rb +0 -13
@@ -11,19 +11,17 @@ require 'tmpdir'
11
11
  # \
12
12
  # B
13
13
 
14
- class ESTPT
15
- def a
16
- 100.times{b}
17
- 300.times{c}
18
- c;c;c
14
+ module MethodElimination
15
+ def self.a
16
+ 1.times {|i| c}
19
17
  end
20
18
 
21
- def b
22
- sleep 0
19
+ def self.b
20
+ sleep 0.1
23
21
  end
24
22
 
25
- def c
26
- 5.times{b}
23
+ def self.c
24
+ 1.times {|i| b}
27
25
  end
28
26
  end
29
27
 
@@ -40,24 +38,37 @@ class MethodEliminationTest < Test::Unit::TestCase
40
38
  method_infos = result.threads.first.methods
41
39
  assert(m1 = method_infos[0])
42
40
  assert(c1 = m1.call_infos.first)
43
- assert_equal(c1, c1.parent = c1)
44
- assert_equal c1, c1.parent
41
+ assert_nil(c1.parent)
45
42
  end
46
43
 
47
44
  def test_methods_can_be_eliminated
48
45
  RubyProf.start
49
- 5.times{ESTPT.new.a}
46
+ 5.times {MethodElimination.a}
50
47
  result = RubyProf.stop
51
- # result.dump
52
- eliminated = result.eliminate_methods!([/Integer#times/])
53
- # puts eliminated.inspect
54
- # result.dump
55
- eliminated.each do |m|
56
- assert_method_has_been_eliminated(result, m)
57
- end
48
+
49
+ methods = result.threads.first.methods.sort.reverse
50
+
51
+ assert_equal(6, methods.count)
52
+ assert_equal('MethodEliminationTest#test_methods_can_be_eliminated', methods[0].full_name)
53
+ assert_equal('Integer#times', methods[1].full_name)
54
+ assert_equal('<Module::MethodElimination>#a', methods[2].full_name)
55
+ assert_equal('<Module::MethodElimination>#c', methods[3].full_name)
56
+ assert_equal('<Module::MethodElimination>#b', methods[4].full_name)
57
+ assert_equal('Kernel#sleep', methods[5].full_name)
58
+
59
+ result.eliminate_methods!([/Integer#times/])
60
+
61
+ methods = result.threads.first.methods.sort.reverse
62
+ assert_equal(5, methods.count)
63
+ assert_equal('MethodEliminationTest#test_methods_can_be_eliminated', methods[0].full_name)
64
+ assert_equal('<Module::MethodElimination>#a', methods[1].full_name)
65
+ assert_equal('<Module::MethodElimination>#c', methods[2].full_name)
66
+ assert_equal('<Module::MethodElimination>#b', methods[3].full_name)
67
+ assert_equal('Kernel#sleep', methods[4].full_name)
58
68
  end
59
69
 
60
70
  private
71
+
61
72
  def assert_method_has_been_eliminated(result, eliminated_method)
62
73
  result.threads.each do |thread|
63
74
  thread.methods.each do |method|
@@ -4,22 +4,72 @@
4
4
  require File.expand_path('../test_helper', __FILE__)
5
5
 
6
6
  class PauseResumeTest < Test::Unit::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
+ assert_equal(3, methods.length)
35
+
36
+ # Check the names
37
+ assert_equal('<Class::RubyProf::C1>#hello', methods[0].full_name)
38
+ assert_equal('Kernel#sleep', methods[1].full_name)
39
+ assert_equal('PauseResumeTest#test_pause_resume', methods[2].full_name)
40
+
41
+ # Check times
42
+ assert_in_delta(0.2, methods[0].total_time, 0.01)
43
+ assert_in_delta(0, methods[0].wait_time, 0.01)
44
+ assert_in_delta(0, methods[0].self_time, 0.01)
45
+
46
+ assert_in_delta(0.2, methods[1].total_time, 0.01)
47
+ assert_in_delta(0, methods[1].wait_time, 0.01)
48
+ assert_in_delta(0.2, methods[1].self_time, 0.01)
49
+
50
+ assert_in_delta(0.2, methods[2].total_time, 0.01)
51
+ assert_in_delta(0, methods[2].wait_time, 0.01)
52
+ assert_in_delta(0, methods[2].self_time, 0.01)
53
+ end
7
54
 
8
55
  # pause/resume in the same frame
9
56
  def test_pause_resume_1
10
- p= RubyProf::Profile.new(RubyProf::WALL_TIME,[])
57
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
11
58
 
12
- p.start
59
+ # Measured
60
+ profile.start
13
61
  method_1a
14
62
 
15
- p.pause
63
+ # Not measured
64
+ profile.pause
16
65
  method_1b
17
66
 
18
- p.resume
67
+ # Measured
68
+ profile.resume
19
69
  method_1c
20
70
 
21
- r= p.stop
22
- assert_in_delta(0.6, r.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05)
71
+ result = profile.stop
72
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05)
23
73
  end
24
74
  def method_1a; sleep 0.2 end
25
75
  def method_1b; sleep 1 end
@@ -27,35 +77,92 @@ class PauseResumeTest < Test::Unit::TestCase
27
77
 
28
78
  # pause in parent frame, resume in child
29
79
  def test_pause_resume_2
30
- p= RubyProf::Profile.new(RubyProf::WALL_TIME,[])
80
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
31
81
 
32
- p.start
82
+ # Measured
83
+ profile.start
33
84
  method_2a
34
85
 
35
- p.pause
86
+ # Not Measured
87
+ profile.pause
36
88
  sleep 0.5
37
- method_2b(p)
89
+ method_2b(profile)
38
90
 
39
- r= p.stop
40
- assert_in_delta(0.6, r.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05)
91
+ result = profile.stop
92
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05)
41
93
  end
42
94
  def method_2a; sleep 0.2 end
43
- def method_2b(p); sleep 0.5; p.resume; sleep 0.4 end
95
+ def method_2b(profile); sleep 0.5; profile.resume; sleep 0.4 end
44
96
 
45
97
  # pause in child frame, resume in parent
46
98
  def test_pause_resume_3
47
- p= RubyProf::Profile.new(RubyProf::WALL_TIME,[])
48
-
49
- p.start
50
- method_3a(p)
99
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
51
100
 
101
+ # Measured
102
+ profile.start
103
+ method_3a(profile)
52
104
  sleep 0.5
53
- p.resume
105
+
106
+ profile.resume
54
107
  method_3b
55
108
 
56
- r= p.stop
57
- assert_in_delta(0.6, r.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05)
109
+ result = profile.stop
110
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05)
58
111
  end
59
- def method_3a(p); sleep 0.2; p.pause; sleep 0.5 end
112
+ def method_3a(profile); sleep 0.2; profile.pause; sleep 0.5 end
60
113
  def method_3b; sleep 0.4 end
61
- end
114
+
115
+ def test_pause_seq
116
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
117
+ profile.start ; assert !profile.paused?
118
+ profile.pause ; assert profile.paused?
119
+ profile.resume; assert !profile.paused?
120
+ profile.pause ; assert profile.paused?
121
+ profile.pause ; assert profile.paused?
122
+ profile.resume; assert !profile.paused?
123
+ profile.resume; assert !profile.paused?
124
+ profile.stop ; assert !profile.paused?
125
+ end
126
+
127
+ def test_pause_block
128
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
129
+ profile.start
130
+ profile.pause
131
+ assert profile.paused?
132
+
133
+ times_block_invoked = 0
134
+ retval= profile.resume{
135
+ times_block_invoked += 1
136
+ 120 + times_block_invoked
137
+ }
138
+ assert_equal 1, times_block_invoked
139
+ assert profile.paused?
140
+
141
+ assert_equal 121, retval, "resume() should return the result of the given block."
142
+
143
+ profile.stop
144
+ end
145
+
146
+ def test_pause_block_with_error
147
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
148
+ profile.start
149
+ profile.pause
150
+ assert profile.paused?
151
+
152
+ begin
153
+ profile.resume{ raise }
154
+ flunk 'Exception expected.'
155
+ rescue
156
+ assert profile.paused?
157
+ end
158
+
159
+ profile.stop
160
+ end
161
+
162
+ def test_resume_when_not_paused
163
+ profile = RubyProf::Profile.new(RubyProf::WALL_TIME,[])
164
+ profile.start ; assert !profile.paused?
165
+ profile.resume; assert !profile.paused?
166
+ profile.stop ; assert !profile.paused?
167
+ end
168
+ end
@@ -34,7 +34,6 @@ def find_largest(primes)
34
34
  # Intentionally use upto for example purposes
35
35
  # (upto is also called from is_prime)
36
36
  0.upto(primes.length-1) do |i|
37
- sleep(0.02)
38
37
  prime = primes[i]
39
38
  if prime > largest
40
39
  largest = prime
@@ -7,20 +7,11 @@ require 'fileutils'
7
7
 
8
8
  # -- Tests ----
9
9
  class PrintersTest < Test::Unit::TestCase
10
- def go
11
- run_primes(1000)
12
- end
13
-
14
10
  def setup
15
11
  # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
16
12
  RubyProf::measure_mode = RubyProf::WALL_TIME
17
13
  @result = RubyProf.profile do
18
- begin
19
- run_primes(1000)
20
- go
21
- rescue => e
22
- p e
23
- end
14
+ run_primes(200)
24
15
  end
25
16
  end
26
17
 
@@ -45,7 +36,6 @@ class PrintersTest < Test::Unit::TestCase
45
36
 
46
37
  printer = RubyProf::GraphPrinter.new(@result)
47
38
  printer.print(output)
48
-
49
39
  end
50
40
  end
51
41
 
@@ -111,9 +101,9 @@ class PrintersTest < Test::Unit::TestCase
111
101
  printer = RubyProf::GraphHtmlPrinter.new(@result)
112
102
  printer.print(output)
113
103
 
114
- assert_match( /DTD HTML 4\.01/i, output )
115
- assert_match( %r{<th>Total Time</th>}i, output )
116
- assert_match( /Object#run_primes/i, output )
104
+ assert_match(/DTD HTML 4\.01/i, output)
105
+ assert_match( %r{<th>Total Time</th>}i, output)
106
+ assert_match(/Object#run_primes/i, output)
117
107
  end
118
108
 
119
109
  def test_graph_string
@@ -121,9 +111,9 @@ class PrintersTest < Test::Unit::TestCase
121
111
  printer = RubyProf::GraphPrinter.new(@result)
122
112
  printer.print(output)
123
113
 
124
- assert_match( /Thread ID: -?\d+/i, output )
125
- assert_match( /Total Time: \d+\.\d+/i, output )
126
- assert_match( /Object#run_primes/i, output )
114
+ assert_match(/Thread ID: -?\d+/i, output)
115
+ assert_match(/Total Time: \d+\.\d+/i, output)
116
+ assert_match(/Object#run_primes/i, output)
127
117
  end
128
118
 
129
119
  def test_call_tree_string
@@ -262,5 +252,4 @@ class PrintersTest < Test::Unit::TestCase
262
252
  array = array.map{|n| n.to_f} # allow for > 10s times to sort right, since lexographically 4.0 > 10.0
263
253
  assert_equal array, array.sort.reverse, "Array #{array.inspect} is not sorted"
264
254
  end
265
-
266
255
  end
@@ -43,17 +43,13 @@ class RecursiveTest < Test::Unit::TestCase
43
43
  simple(2)
44
44
  end
45
45
 
46
- methods = result.threads.first.methods.dup
47
-
48
46
  # Remove Fixnum+, Fixnum== for less than Ruby 1.9
49
- methods.delete_if do |method|
50
- method.full_name.match(/Fixnum/)
51
- end
47
+ result.eliminate_methods!(%w(Fixnum#== Fixnum#-))
52
48
 
49
+ methods = result.threads.first.methods.sort.reverse
53
50
  assert_equal(3, methods.length)
54
51
 
55
52
  # Method 0: RecursiveTest#test_simple
56
- methods.sort!.reverse!
57
53
  method = methods[0]
58
54
  assert_equal('RecursiveTest#test_simple', method.full_name)
59
55
  assert_equal(1, method.called)
@@ -80,12 +76,12 @@ class RecursiveTest < Test::Unit::TestCase
80
76
  assert_equal(2, method.call_infos.length)
81
77
 
82
78
  call_info = method.call_infos.first
83
- assert_equal(2 + (RUBY_VERSION < '1.9.0' ? 2 : 0), call_info.children.length)
79
+ assert_equal(2, call_info.children.length)
84
80
  assert_equal('RecursiveTest#test_simple->Object#simple', call_info.call_sequence)
85
81
  assert(!call_info.recursive)
86
82
 
87
83
  call_info = method.call_infos.last
88
- assert_equal(1 + (RUBY_VERSION < '1.9.0' ? 2 : 0), call_info.children.length)
84
+ assert_equal(1, call_info.children.length)
89
85
  assert_equal('RecursiveTest#test_simple->Object#simple->Object#simple', call_info.call_sequence)
90
86
  assert(call_info.recursive)
91
87
 
@@ -107,43 +103,6 @@ class RecursiveTest < Test::Unit::TestCase
107
103
  assert_equal('RecursiveTest#test_simple->Object#simple->Object#simple->Kernel#sleep', call_info.call_sequence)
108
104
  assert_equal(0, call_info.children.length)
109
105
  assert(!call_info.recursive)
110
-
111
- if RUBY_VERSION < '1.9'
112
- methods = result.threads.first.methods.dup.sort!.reverse!
113
- method = methods[3]
114
- assert_equal('Fixnum#-', method.full_name)
115
- assert_equal(2, method.called)
116
- assert_in_delta(0, method.total_time, 0.01)
117
- assert_in_delta(0, method.self_time, 0.01)
118
- assert_in_delta(0, method.wait_time, 0.01)
119
- assert_in_delta(0, method.children_time, 0.01)
120
-
121
- assert_equal(2, method.call_infos.length)
122
- call_info = method.call_infos[0]
123
- assert_equal('RecursiveTest#test_simple->Object#simple->Fixnum#-', call_info.call_sequence)
124
- assert_equal(0, call_info.children.length)
125
-
126
- call_info = method.call_infos[1]
127
- assert_equal('RecursiveTest#test_simple->Object#simple->Object#simple->Fixnum#-', call_info.call_sequence)
128
- assert_equal(0, call_info.children.length)
129
-
130
- method = methods[4]
131
- assert_equal('Fixnum#==', method.full_name)
132
- assert_equal(2, method.called)
133
- assert_in_delta(0, method.total_time, 0.01)
134
- assert_in_delta(0, method.self_time, 0.01)
135
- assert_in_delta(0, method.wait_time, 0.01)
136
- assert_in_delta(0, method.children_time, 0.01)
137
-
138
- assert_equal(2, method.call_infos.length)
139
- call_info = method.call_infos[0]
140
- assert_equal('RecursiveTest#test_simple->Object#simple->Fixnum#==', call_info.call_sequence)
141
- assert_equal(0, call_info.children.length)
142
-
143
- call_info = method.call_infos[1]
144
- assert_equal('RecursiveTest#test_simple->Object#simple->Object#simple->Fixnum#==', call_info.call_sequence)
145
- assert_equal(0, call_info.children.length)
146
- end
147
106
  end
148
107
 
149
108
  def test_cycle
@@ -151,9 +110,6 @@ class RecursiveTest < Test::Unit::TestCase
151
110
  render
152
111
  end
153
112
 
154
- printer = RubyProf::GraphPrinter.new(result)
155
- printer.print(STDOUT)
156
-
157
113
  methods = result.threads.first.methods.sort.reverse
158
114
  if RUBY_VERSION < '1.9' # Fixnum#+, Fixnum#===, Kernel#===
159
115
  assert_equal(8, methods.length)
@@ -1,16 +1,21 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ # Make ruby 1.8.7 happy
4
+ require "rubygems"
5
+
3
6
  # Make RubyMine happy
7
+ gem "minitest"
8
+
4
9
  if ENV["RM_INFO"] || ENV["TEAMCITY_VERSION"]
5
- gem 'win32console'
6
- gem 'minitest-reporters'
10
+ if RUBY_PLATFORM =~ /(win32|mingw)/
11
+ gem "win32console"
12
+ end
13
+ gem "minitest-reporters"
7
14
  require 'minitest/reporters'
8
- MiniTest::Unit.runner = MiniTest::SuiteRunner.new
9
- MiniTest::Unit.runner.reporters << MiniTest::Reporters::RubyMineReporter.new
15
+ MiniTest::Reporters.use!
10
16
  end
11
17
 
12
18
  # To make testing/debugging easier, test within this source tree versus an installed gem
13
-
14
19
  dir = File.dirname(__FILE__)
15
20
  root = File.expand_path(File.join(dir, '..'))
16
21
  lib = File.expand_path(File.join(root, 'lib'))
@@ -71,11 +76,26 @@ module RubyProf
71
76
  goodbye
72
77
  end
73
78
  end
74
-
75
- if RUBY_VERSION < '1.9'
76
- PARENT = Object
77
- else
78
- PARENT = BasicObject
79
+
80
+ def self.ruby_major_version
81
+ match = RUBY_VERSION.match(/(\d)\.(\d)/)
82
+ return Integer(match[1])
79
83
  end
80
84
 
85
+ def self.ruby_minor_version
86
+ match = RUBY_VERSION.match(/(\d)\.(\d)/)
87
+ return Integer(match[2])
88
+ end
89
+
90
+ def self.parent_object
91
+ if ruby_major_version == 1 && ruby_minor_version == 8
92
+ Object
93
+ else
94
+ BasicObject
95
+ end
96
+ end
97
+
98
+ def self.ruby_2?
99
+ ruby_major_version == 2
100
+ end
81
101
  end