ruby-prof 0.7.0-x86-mswin32-60 → 0.7.1-x86-mswin32-60

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.
data/CHANGES CHANGED
@@ -1,3 +1,24 @@
1
+ 0.7.1 (2008-11-28)
2
+ ========================
3
+ * Added new AggregateCallInfo class for printers to
4
+ make results easier to read. Take this call sequence
5
+ for example:
6
+
7
+ A B C
8
+ | | |
9
+ Z A A
10
+ | |
11
+ Z Z
12
+
13
+ By default, ruby-prof will show that Z was called by 3 separate
14
+ instances of A. In an IDE that is helpful but in a text report
15
+ it is not since it makes the report much harder to read.
16
+ As a result, printers now aggregate together callers (and children),
17
+ matching ruby-prof's output from versions prior to 0.7.0.
18
+
19
+ * Fixes for supporting x86_64 machines (Matt Sanford)
20
+
21
+
1
22
  0.7.0 (2008-11-04)
2
23
  ========================
3
24
 
data/README CHANGED
@@ -33,7 +33,9 @@ The easiest way to install ruby-prof is by using Ruby Gems. To install:
33
33
  <tt>gem install ruby-prof</tt>
34
34
 
35
35
  If you are running Windows, make sure to install the Win32 RubyGem which
36
- includes a pre-built binary.
36
+ includes a pre-built binary. Due to a bug in ruby-gems, you cannot
37
+ install the gem to a path that contains spaces
38
+ (see http://rubyforge.org/tracker/?func=detail&aid=23003&group_id=126&atid=577).
37
39
 
38
40
  ruby-prof is also available as a tarred gzip archive and zip archive.
39
41
 
data/Rakefile CHANGED
@@ -117,7 +117,7 @@ task :default => :package
117
117
  desc 'Run the ruby-prof test suite'
118
118
  Rake::TestTask.new do |t|
119
119
  t.libs += %w(lib ext test)
120
- t.test_files = Dir['test/*_test.rb'] - %w(test/profile_unit_test.rb)
120
+ t.test_files = Dir['test/test_suite.rb']
121
121
  t.verbose = true
122
122
  t.warning = true
123
123
  end
@@ -26,7 +26,7 @@
26
26
 
27
27
  #include <ruby.h>
28
28
 
29
- #if defined(_WIN32) || (defined(__GNUC__) && (defined(__i386__) || defined(__powerpc__) || defined(__ppc__)))
29
+ #if defined(_WIN32) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__)))
30
30
  #define MEASURE_CPU_TIME 2
31
31
 
32
32
  static unsigned long long cpu_frequency;
@@ -36,7 +36,7 @@ static unsigned long long cpu_frequency;
36
36
  static prof_measure_t
37
37
  measure_cpu_time()
38
38
  {
39
- #if defined(__i386__)
39
+ #if defined(__i386__) || defined(__x86_64__)
40
40
  unsigned long long x;
41
41
  __asm__ __volatile__ ("rdtsc" : "=A" (x));
42
42
  return x;
@@ -15,7 +15,7 @@ task :install do
15
15
  # RUBYLIBDIR=#{dest_path}
16
16
 
17
17
  dest_path = ENV['RUBYLIBDIR']
18
-
18
+
19
19
  # Copy the extension
20
20
  cp(EXTENSION_NAME, dest_path)
21
21
  end
Binary file
@@ -1,4 +1,4 @@
1
- #define RUBY_PROF_VERSION "0.7.0"
1
+ #define RUBY_PROF_VERSION "0.7.1"
2
2
  #define RUBY_PROF_VERSION_MAJ 0
3
3
  #define RUBY_PROF_VERSION_MIN 7
4
- #define RUBY_PROF_VERSION_MIC 0
4
+ #define RUBY_PROF_VERSION_MIC 1
@@ -2,6 +2,7 @@ require "ruby_prof.so"
2
2
 
3
3
  require "ruby-prof/method_info"
4
4
  require "ruby-prof/call_info"
5
+ require "ruby-prof/aggregate_call_info"
5
6
  require "ruby-prof/flat_printer"
6
7
  require "ruby-prof/graph_printer"
7
8
  require "ruby-prof/graph_html_printer"
@@ -37,6 +37,5 @@ module RubyProf
37
37
  end
38
38
  name
39
39
  end
40
-
41
40
  end
42
41
  end
@@ -0,0 +1,62 @@
1
+ module RubyProf
2
+ class AggregateCallInfo
3
+ attr_reader :call_infos
4
+ def initialize(call_infos)
5
+ if call_infos.length == 0
6
+ raise(ArgumentError, "Must specify at least one call info.")
7
+ end
8
+ @call_infos = call_infos
9
+ end
10
+
11
+ def target
12
+ call_infos.first.target
13
+ end
14
+
15
+ def parent
16
+ call_infos.first.parent
17
+ end
18
+
19
+ def line
20
+ call_infos.first.line
21
+ end
22
+
23
+ def children
24
+ call_infos.inject(Array.new) do |result, call_info|
25
+ result.concat(call_info.children)
26
+ end
27
+ end
28
+
29
+ def total_time
30
+ aggregate(:total_time)
31
+ end
32
+
33
+ def self_time
34
+ aggregate(:self_time)
35
+ end
36
+
37
+ def wait_time
38
+ aggregate(:wait_time)
39
+ end
40
+
41
+ def children_time
42
+ aggregate(:children_time)
43
+ end
44
+
45
+ def called
46
+ aggregate(:called)
47
+ end
48
+
49
+ def to_s
50
+ "#{call_infos.first.full_name}"
51
+ end
52
+
53
+ private
54
+
55
+ def aggregate(method_name)
56
+ self.call_infos.inject(0) do |sum, call_info|
57
+ sum += call_info.send(method_name)
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -39,7 +39,7 @@ module RubyProf
39
39
  def root?
40
40
  self.parent.nil?
41
41
  end
42
-
42
+
43
43
  def to_s
44
44
  "#{call_sequence}"
45
45
  end
@@ -198,7 +198,7 @@ module RubyProf
198
198
  self_percentage = (method.self_time/total_time) * 100 %>
199
199
 
200
200
  <!-- Parents -->
201
- <% for caller in method.call_infos
201
+ <% for caller in method.aggregate_parents
202
202
  next unless caller.parent
203
203
  next if min_time && caller.total_time < min_time %>
204
204
  <tr>
@@ -228,7 +228,7 @@ module RubyProf
228
228
  </tr>
229
229
 
230
230
  <!-- Children -->
231
- <% for callee in method.children %>
231
+ <% for callee in method.aggregate_children %>
232
232
  <% next if min_time && callee.total_time < min_time %>
233
233
  <tr>
234
234
  <td>&nbsp;</td>
@@ -127,7 +127,7 @@ module RubyProf
127
127
  end
128
128
 
129
129
  def print_parents(thread_id, method)
130
- method.call_infos.each do |caller|
130
+ method.aggregate_parents.each do |caller|
131
131
  next unless caller.parent
132
132
  @output << " " * 2 * PERCENTAGE_WIDTH
133
133
  @output << sprintf("%#{TIME_WIDTH}.2f", caller.total_time)
@@ -143,7 +143,7 @@ module RubyProf
143
143
  end
144
144
 
145
145
  def print_children(method)
146
- method.children.each do |child|
146
+ method.aggregate_children.each do |child|
147
147
  # Get children method
148
148
 
149
149
  @output << " " * 2 * PERCENTAGE_WIDTH
@@ -0,0 +1,10 @@
1
+ unless Enumerable.method_defined?(:group_by)
2
+ module Enumerable
3
+ def group_by
4
+ inject(Hash.new) do |result, element|
5
+ (result[yield(element)] ||= []) << element
6
+ result
7
+ end
8
+ end
9
+ end
10
+ end
@@ -48,14 +48,6 @@ module RubyProf
48
48
  end
49
49
  end
50
50
 
51
- def children
52
- @children ||= begin
53
- call_infos.map do |call_info|
54
- call_info.children
55
- end.flatten
56
- end
57
- end
58
-
59
51
  def children_time
60
52
  @children_time ||= begin
61
53
  call_infos.inject(0) do |sum, call_info|
@@ -78,8 +70,38 @@ module RubyProf
78
70
  end
79
71
  end
80
72
 
73
+ def children
74
+ @children ||= begin
75
+ call_infos.map do |call_info|
76
+ call_info.children
77
+ end.flatten
78
+ end
79
+ end
80
+
81
+ def aggregate_parents
82
+ aggregate_call_infos(self.call_infos)
83
+ end
84
+
85
+ def aggregate_children
86
+ aggregate_call_infos(self.children)
87
+ end
88
+
81
89
  def to_s
82
90
  full_name
83
91
  end
92
+
93
+ private
94
+
95
+ def aggregate_call_infos(call_infos)
96
+ groups = call_infos.inject(Hash.new) do |hash, call_info|
97
+ key = call_info.parent ? call_info.parent.target : self
98
+ (hash[key] ||= []) << call_info
99
+ hash
100
+ end
101
+
102
+ groups.map do |key, value|
103
+ AggregateCallInfo.new(value)
104
+ end
105
+ end
84
106
  end
85
107
  end
@@ -0,0 +1,14 @@
1
+ <!-- Generator: GNU source-highlight 2.9
2
+ by Lorenzo Bettini
3
+ http://www.lorenzobettini.it
4
+ http://www.gnu.org/software/src-highlite -->
5
+ <pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'../profile_test_helper'</span>
6
+
7
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ExampleTest <span style="color: #990000">&lt;</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
8
+ <span style="font-weight: bold"><span style="color: #0000FF">include</span></span> RubyProf<span style="color: #990000">::</span>Test
9
+
10
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_stuff
11
+ puts <span style="color: #FF0000">"Test method"</span>
12
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
13
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
14
+ </tt></pre>
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+
6
+ # Test data
7
+ # A B C
8
+ # | | |
9
+ # Z A A
10
+ # | |
11
+ # Z Z
12
+
13
+ class AggClass
14
+ def z
15
+ sleep 1
16
+ end
17
+
18
+ def a
19
+ z
20
+ end
21
+
22
+ def b
23
+ a
24
+ end
25
+
26
+ def c
27
+ a
28
+ end
29
+ end
30
+
31
+ class AggregateTest < Test::Unit::TestCase
32
+ def setup
33
+ # Need to use wall time for this test due to the sleep calls
34
+ RubyProf::measure_mode = RubyProf::WALL_TIME
35
+ end
36
+
37
+ def test_call_infos
38
+ c1 = AggClass.new
39
+ result = RubyProf.profile do
40
+ c1.a
41
+ c1.b
42
+ c1.c
43
+ end
44
+
45
+ methods = result.threads.values.first.sort.reverse
46
+ method = methods.find {|method| method.full_name == 'AggClass#z'}
47
+
48
+ # Check AggClass#z
49
+ assert_equal('AggClass#z', method.full_name)
50
+ assert_equal(3, method.called)
51
+ assert_in_delta(3, method.total_time, 0.01)
52
+ assert_in_delta(0, method.wait_time, 0.01)
53
+ assert_in_delta(0, method.self_time, 0.01)
54
+ assert_in_delta(3, method.children_time, 0.01)
55
+ assert_equal(3, method.call_infos.length)
56
+
57
+ call_info = method.call_infos[0]
58
+ assert_equal('AggregateTest#test_call_infos->AggClass#a->AggClass#z', call_info.call_sequence)
59
+ assert_equal(1, call_info.children.length)
60
+
61
+ call_info = method.call_infos[1]
62
+ assert_equal('AggregateTest#test_call_infos->AggClass#b->AggClass#a->AggClass#z', call_info.call_sequence)
63
+ assert_equal(1, call_info.children.length)
64
+
65
+ call_info = method.call_infos[2]
66
+ assert_equal('AggregateTest#test_call_infos->AggClass#c->AggClass#a->AggClass#z', call_info.call_sequence)
67
+ assert_equal(1, call_info.children.length)
68
+ end
69
+
70
+ def test_aggregates_parents
71
+ c1 = AggClass.new
72
+ result = RubyProf.profile do
73
+ c1.a
74
+ c1.b
75
+ c1.c
76
+ end
77
+
78
+ methods = result.threads.values.first.sort.reverse
79
+ method = methods.find {|method| method.full_name == 'AggClass#z'}
80
+
81
+ # Check AggClass#z
82
+ assert_equal('AggClass#z', method.full_name)
83
+
84
+ call_infos = method.aggregate_parents
85
+ assert_equal(1, call_infos.length)
86
+
87
+ call_info = call_infos.first
88
+ assert_equal('AggClass#a', call_info.parent.target.full_name)
89
+ assert_in_delta(3, call_info.total_time, 0.01)
90
+ assert_in_delta(0, call_info.wait_time, 0.01)
91
+ assert_in_delta(0, call_info.self_time, 0.01)
92
+ assert_in_delta(3, call_info.children_time, 0.01)
93
+ assert_equal(3, call_info.called)
94
+ end
95
+
96
+ def test_aggregates_children
97
+ c1 = AggClass.new
98
+ result = RubyProf.profile do
99
+ c1.a
100
+ c1.b
101
+ c1.c
102
+ end
103
+
104
+ methods = result.threads.values.first.sort.reverse
105
+ method = methods.find {|method| method.full_name == 'AggClass#a'}
106
+
107
+ # Check AggClass#a
108
+ assert_equal('AggClass#a', method.full_name)
109
+
110
+ call_infos = method.aggregate_children
111
+ assert_equal(1, call_infos.length)
112
+
113
+ call_info = call_infos.first
114
+ assert_equal('AggClass#z', call_info.target.full_name)
115
+ assert_in_delta(3, call_info.total_time, 0.01)
116
+ assert_in_delta(0, call_info.wait_time, 0.01)
117
+ assert_in_delta(0, call_info.self_time, 0.01)
118
+ assert_in_delta(3, call_info.children_time, 0.01)
119
+ assert_equal(3, call_info.called)
120
+ end
121
+ end
@@ -10,7 +10,7 @@ require 'ruby-prof'
10
10
  # \
11
11
  # B
12
12
 
13
- class C1
13
+ class StackClass
14
14
  def a
15
15
  sleep 1
16
16
  b
@@ -34,17 +34,17 @@ class StackTest < Test::Unit::TestCase
34
34
  end
35
35
 
36
36
  def test_call_sequence
37
- c = C1.new
37
+ c = StackClass.new
38
38
  result = RubyProf.profile do
39
39
  c.a
40
40
  end
41
41
 
42
42
  # Length should be 5:
43
43
  # StackTest#test_call_sequence
44
- # C1#a
44
+ # StackClass#a
45
45
  # Kernel#sleep
46
- # C1#c
47
- # C1#b
46
+ # StackClass#c
47
+ # StackClass#b
48
48
 
49
49
  methods = result.threads.values.first.sort.reverse
50
50
  assert_equal(5, methods.length)
@@ -63,9 +63,9 @@ class StackTest < Test::Unit::TestCase
63
63
  assert_equal('StackTest#test_call_sequence', call_info.call_sequence)
64
64
  assert_equal(1, call_info.children.length)
65
65
 
66
- # Check C1#a
66
+ # Check StackClass#a
67
67
  method = methods[1]
68
- assert_equal('C1#a', method.full_name)
68
+ assert_equal('StackClass#a', method.full_name)
69
69
  assert_equal(1, method.called)
70
70
  assert_in_delta(8, method.total_time, 0.01)
71
71
  assert_in_delta(0, method.wait_time, 0.01)
@@ -74,7 +74,7 @@ class StackTest < Test::Unit::TestCase
74
74
  assert_equal(1, method.call_infos.length)
75
75
 
76
76
  call_info = method.call_infos[0]
77
- assert_equal('StackTest#test_call_sequence->C1#a', call_info.call_sequence)
77
+ assert_equal('StackTest#test_call_sequence->StackClass#a', call_info.call_sequence)
78
78
  assert_equal(3, call_info.children.length)
79
79
 
80
80
  # Check Kernel#sleep
@@ -88,24 +88,24 @@ class StackTest < Test::Unit::TestCase
88
88
  assert_equal(4, method.call_infos.length)
89
89
 
90
90
  call_info = method.call_infos[0]
91
- assert_equal('StackTest#test_call_sequence->C1#a->Kernel#sleep', call_info.call_sequence)
91
+ assert_equal('StackTest#test_call_sequence->StackClass#a->Kernel#sleep', call_info.call_sequence)
92
92
  assert_equal(0, call_info.children.length)
93
93
 
94
94
  call_info = method.call_infos[1]
95
- assert_equal('StackTest#test_call_sequence->C1#a->C1#b->Kernel#sleep', call_info.call_sequence)
95
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#b->Kernel#sleep', call_info.call_sequence)
96
96
  assert_equal(0, call_info.children.length)
97
97
 
98
98
  call_info = method.call_infos[2]
99
- assert_equal('StackTest#test_call_sequence->C1#a->C1#c->Kernel#sleep', call_info.call_sequence)
99
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#c->Kernel#sleep', call_info.call_sequence)
100
100
  assert_equal(0, call_info.children.length)
101
101
 
102
102
  call_info = method.call_infos[3]
103
- assert_equal('StackTest#test_call_sequence->C1#a->C1#c->C1#b->Kernel#sleep', call_info.call_sequence)
103
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#c->StackClass#b->Kernel#sleep', call_info.call_sequence)
104
104
  assert_equal(0, call_info.children.length)
105
105
 
106
- # Check C1#c
106
+ # Check StackClass#c
107
107
  method = methods[3]
108
- assert_equal('C1#c', method.full_name)
108
+ assert_equal('StackClass#c', method.full_name)
109
109
  assert_equal(1, method.called)
110
110
  assert_in_delta(5, method.total_time, 0.01)
111
111
  assert_in_delta(0, method.wait_time, 0.01)
@@ -114,12 +114,12 @@ class StackTest < Test::Unit::TestCase
114
114
  assert_equal(1, method.call_infos.length)
115
115
 
116
116
  call_info = method.call_infos[0]
117
- assert_equal('StackTest#test_call_sequence->C1#a->C1#c', call_info.call_sequence)
117
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#c', call_info.call_sequence)
118
118
  assert_equal(2, call_info.children.length)
119
119
 
120
- # Check C1#b
120
+ # Check StackClass#b
121
121
  method = methods[4]
122
- assert_equal('C1#b', method.full_name)
122
+ assert_equal('StackClass#b', method.full_name)
123
123
  assert_equal(2, method.called)
124
124
  assert_in_delta(4, method.total_time, 0.01)
125
125
  assert_in_delta(0, method.wait_time, 0.01)
@@ -128,11 +128,11 @@ class StackTest < Test::Unit::TestCase
128
128
  assert_equal(2, method.call_infos.length)
129
129
 
130
130
  call_info = method.call_infos[0]
131
- assert_equal('StackTest#test_call_sequence->C1#a->C1#b', call_info.call_sequence)
131
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#b', call_info.call_sequence)
132
132
  assert_equal(1, call_info.children.length)
133
133
 
134
134
  call_info = method.call_infos[1]
135
- assert_equal('StackTest#test_call_sequence->C1#a->C1#c->C1#b', call_info.call_sequence)
135
+ assert_equal('StackTest#test_call_sequence->StackClass#a->StackClass#c->StackClass#b', call_info.call_sequence)
136
136
  assert_equal(1, call_info.children.length)
137
137
  end
138
138
  end
@@ -1,5 +1,6 @@
1
1
  require 'test/unit'
2
2
 
3
+ require 'aggregate_test'
3
4
  require 'basic_test'
4
5
  require 'duplicate_names_test'
5
6
  require 'exceptions_test'
@@ -9,7 +10,6 @@ require 'module_test'
9
10
  require 'no_method_class_test'
10
11
  require 'prime_test'
11
12
  require 'printers_test'
12
- require 'profile_unit_test'
13
13
  require 'recursive_test'
14
14
  require 'singleton_test'
15
15
  require 'stack_test'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: x86-mswin32-60
6
6
  authors:
7
7
  - Shugo Maeda and Charlie Savage
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-11 00:00:00 -07:00
12
+ date: 2008-11-30 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -49,11 +49,13 @@ files:
49
49
  - ext/vc/ruby_prof.vcproj
50
50
  - lib/ruby-prof
51
51
  - lib/ruby-prof/abstract_printer.rb
52
+ - lib/ruby-prof/aggregate_call_info.rb
52
53
  - lib/ruby-prof/call_info.rb
53
54
  - lib/ruby-prof/call_tree_printer.rb
54
55
  - lib/ruby-prof/flat_printer.rb
55
56
  - lib/ruby-prof/graph_html_printer.rb
56
57
  - lib/ruby-prof/graph_printer.rb
58
+ - lib/ruby-prof/group_by.rb
57
59
  - lib/ruby-prof/method_info.rb
58
60
  - lib/ruby-prof/task.rb
59
61
  - lib/ruby-prof/test.rb
@@ -63,7 +65,9 @@ files:
63
65
  - rails/environment/profile.rb
64
66
  - rails/example
65
67
  - rails/example/example_test.rb
68
+ - rails/example/example_test.rb.html
66
69
  - rails/profile_test_helper.rb
70
+ - test/aggregate_test.rb
67
71
  - test/basic_test.rb
68
72
  - test/duplicate_names_test.rb
69
73
  - test/exceptions_test.rb
@@ -75,7 +79,6 @@ files:
75
79
  - test/prime.rb
76
80
  - test/prime_test.rb
77
81
  - test/printers_test.rb
78
- - test/profile_unit_test.rb
79
82
  - test/recursive_test.rb
80
83
  - test/singleton_test.rb
81
84
  - test/stack_test.rb
@@ -106,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
109
  requirements: []
107
110
 
108
111
  rubyforge_project: ruby-prof
109
- rubygems_version: 1.2.0
112
+ rubygems_version: 1.3.1
110
113
  signing_key:
111
114
  specification_version: 2
112
115
  summary: Fast Ruby profiler
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'test/unit'
3
- require 'ruby-prof'
4
-
5
- # Need to use wall time for this test due to the sleep calls
6
- RubyProf::measure_mode = RubyProf::WALL_TIME
7
-
8
- # -- Tests ----
9
- class ProfileTest < Test::Unit::TestCase
10
- include RubyProf::Test
11
-
12
- def teardown
13
- profile_dir = output_dir
14
-
15
- #file_path = File.join(profile_dir, 'test_profile_profile_test.html')
16
- #assert(File.exists?(file_path))
17
- end
18
-
19
- def test_profile
20
- sleep(1)
21
- end
22
- end