adamh-ruby-prof 0.7.3

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 +202 -0
  2. data/LICENSE +23 -0
  3. data/README +436 -0
  4. data/Rakefile +123 -0
  5. data/bin/ruby-prof +217 -0
  6. data/examples/flat.txt +55 -0
  7. data/examples/graph.html +823 -0
  8. data/examples/graph.txt +170 -0
  9. data/ext/extconf.rb +34 -0
  10. data/ext/measure_allocations.h +58 -0
  11. data/ext/measure_cpu_time.h +152 -0
  12. data/ext/measure_gc_runs.h +76 -0
  13. data/ext/measure_gc_time.h +57 -0
  14. data/ext/measure_memory.h +101 -0
  15. data/ext/measure_process_time.h +52 -0
  16. data/ext/measure_wall_time.h +53 -0
  17. data/ext/mingw/Rakefile +23 -0
  18. data/ext/mingw/build.rake +38 -0
  19. data/ext/ruby_prof.c +1747 -0
  20. data/ext/ruby_prof.h +189 -0
  21. data/ext/vc/ruby_prof.sln +20 -0
  22. data/ext/vc/ruby_prof.vcproj +241 -0
  23. data/ext/version.h +4 -0
  24. data/lib/ruby-prof.rb +48 -0
  25. data/lib/ruby-prof/abstract_printer.rb +41 -0
  26. data/lib/ruby-prof/aggregate_call_info.rb +62 -0
  27. data/lib/ruby-prof/call_info.rb +47 -0
  28. data/lib/ruby-prof/call_tree_printer.rb +84 -0
  29. data/lib/ruby-prof/flat_printer.rb +79 -0
  30. data/lib/ruby-prof/graph_html_printer.rb +256 -0
  31. data/lib/ruby-prof/graph_printer.rb +164 -0
  32. data/lib/ruby-prof/method_info.rb +111 -0
  33. data/lib/ruby-prof/task.rb +146 -0
  34. data/lib/ruby-prof/test.rb +148 -0
  35. data/lib/unprof.rb +8 -0
  36. data/rails/environment/profile.rb +24 -0
  37. data/rails/example/example_test.rb +9 -0
  38. data/rails/profile_test_helper.rb +21 -0
  39. data/test/aggregate_test.rb +121 -0
  40. data/test/basic_test.rb +309 -0
  41. data/test/duplicate_names_test.rb +32 -0
  42. data/test/exceptions_test.rb +15 -0
  43. data/test/exclude_threads_test.rb +54 -0
  44. data/test/line_number_test.rb +73 -0
  45. data/test/measurement_test.rb +121 -0
  46. data/test/module_test.rb +54 -0
  47. data/test/no_method_class_test.rb +13 -0
  48. data/test/prime.rb +58 -0
  49. data/test/prime_test.rb +13 -0
  50. data/test/printers_test.rb +71 -0
  51. data/test/recursive_test.rb +254 -0
  52. data/test/singleton_test.rb +37 -0
  53. data/test/stack_test.rb +138 -0
  54. data/test/start_stop_test.rb +95 -0
  55. data/test/test_suite.rb +23 -0
  56. data/test/thread_test.rb +159 -0
  57. data/test/unique_call_path_test.rb +206 -0
  58. metadata +114 -0
@@ -0,0 +1,8 @@
1
+ require "ruby-prof"
2
+
3
+ at_exit {
4
+ result = RubyProf.stop
5
+ printer = RubyProf::FlatPrinter.new(result)
6
+ printer.print(STDOUT)
7
+ }
8
+ RubyProf.start
@@ -0,0 +1,24 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+ # The profile environment should match the same settings
3
+ # as the production environment to give a reasonalbe
4
+ # approximation of performance. However, it should
5
+ # definitely not use the production databse!
6
+
7
+
8
+ # Cache classes - otherwise your code
9
+ # will run approximately 5 times slower and the
10
+ # profiling results will be overwhelmed by Rails
11
+ # dependency loading mechanism
12
+ config.cache_classes = true
13
+
14
+ # Don't check template timestamps - once again this
15
+ # is to avoid IO times overwhelming profile results
16
+ config.action_view.cache_template_loading = true
17
+
18
+ # This is debatable, but turn off action controller
19
+ # caching to see how long it really takes to run
20
+ # queries and render templates
21
+ config.action_controller.perform_caching = false
22
+
23
+ # Turn off most logging
24
+ config.log_level = :info
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '../profile_test_helper'
2
+
3
+ class ExampleTest < Test::Unit::TestCase
4
+ include RubyProf::Test
5
+
6
+ def test_stuff
7
+ puts "Test method"
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ # Load profile environment
2
+ env = ENV["RAILS_ENV"] = "profile"
3
+ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
4
+
5
+ # Load Rails testing infrastructure
6
+ require 'test_help'
7
+
8
+ # Now we can load test_helper since we've already loaded the
9
+ # profile RAILS environment.
10
+ require File.expand_path(File.join(RAILS_ROOT, 'test', 'test_helper'))
11
+
12
+ # Reset the current environment back to profile
13
+ # since test_helper reset it to test
14
+ ENV["RAILS_ENV"] = env
15
+
16
+ # Now load ruby-prof and away we go
17
+ require 'ruby-prof'
18
+
19
+ # Setup output directory to Rails tmp directory
20
+ RubyProf::Test::PROFILE_OPTIONS[:output_dir] =
21
+ File.expand_path(File.join(RAILS_ROOT, 'tmp', 'profile'))
@@ -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
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+
6
+ class C1
7
+ def C1.hello
8
+ sleep(0.1)
9
+ end
10
+
11
+ def hello
12
+ sleep(0.2)
13
+ end
14
+ end
15
+
16
+ module M1
17
+ def hello
18
+ sleep(0.3)
19
+ end
20
+ end
21
+
22
+ class C2
23
+ include M1
24
+ extend M1
25
+ end
26
+
27
+ class C3
28
+ def hello
29
+ sleep(0.4)
30
+ end
31
+ end
32
+
33
+ module M4
34
+ def hello
35
+ sleep(0.5)
36
+ end
37
+ end
38
+
39
+ module M5
40
+ include M4
41
+ def goodbye
42
+ hello
43
+ end
44
+ end
45
+
46
+ class C6
47
+ include M5
48
+ def test
49
+ goodbye
50
+ end
51
+ end
52
+
53
+ class BasicTest < Test::Unit::TestCase
54
+ def setup
55
+ # Need to use wall time for this test due to the sleep calls
56
+ RubyProf::measure_mode = RubyProf::WALL_TIME
57
+ end
58
+
59
+ def test_running
60
+ assert(!RubyProf.running?)
61
+ RubyProf.start
62
+ assert(RubyProf.running?)
63
+ RubyProf.stop
64
+ assert(!RubyProf.running?)
65
+ end
66
+
67
+ def test_double_profile
68
+ RubyProf.start
69
+ assert_raise(RuntimeError) do
70
+ RubyProf.start
71
+ end
72
+
73
+ assert_raise(RuntimeError) do
74
+ RubyProf.profile do
75
+ puts 1
76
+ end
77
+ end
78
+ RubyProf.stop
79
+ end
80
+
81
+ def test_no_block
82
+ assert_raise(ArgumentError) do
83
+ RubyProf.profile
84
+ end
85
+ end
86
+
87
+ def test_class_methods
88
+ result = RubyProf.profile do
89
+ C1.hello
90
+ end
91
+
92
+ # Length should be 3:
93
+ # BasicTest#test_class_methods
94
+ # <Class::C1>#hello
95
+ # Kernel#sleep
96
+
97
+ methods = result.threads.values.first.sort.reverse
98
+ assert_equal(3, methods.length)
99
+
100
+ # Check the names
101
+ assert_equal('BasicTest#test_class_methods', methods[0].full_name)
102
+ assert_equal('<Class::C1>#hello', methods[1].full_name)
103
+ assert_equal('Kernel#sleep', methods[2].full_name)
104
+
105
+ # Check times
106
+ assert_in_delta(0.1, methods[0].total_time, 0.01)
107
+ assert_in_delta(0, methods[0].wait_time, 0.01)
108
+ assert_in_delta(0, methods[0].self_time, 0.01)
109
+
110
+ assert_in_delta(0.1, methods[1].total_time, 0.01)
111
+ assert_in_delta(0, methods[1].wait_time, 0.01)
112
+ assert_in_delta(0, methods[1].self_time, 0.01)
113
+
114
+ assert_in_delta(0.1, methods[2].total_time, 0.01)
115
+ assert_in_delta(0, methods[2].wait_time, 0.01)
116
+ assert_in_delta(0.1, methods[2].self_time, 0.01)
117
+ end
118
+
119
+ def test_instance_methods
120
+ result = RubyProf.profile do
121
+ C1.new.hello
122
+ end
123
+
124
+ # Methods called
125
+ # BasicTest#test_instance_methods
126
+ # Class.new
127
+ # Class:Object#allocate
128
+ # for Object#initialize
129
+ # C1#hello
130
+ # Kernel#sleep
131
+
132
+ methods = result.threads.values.first.sort.reverse
133
+ assert_equal(6, methods.length)
134
+
135
+ assert_equal('BasicTest#test_instance_methods', methods[0].full_name)
136
+ assert_equal('C1#hello', methods[1].full_name)
137
+ assert_equal('Kernel#sleep', methods[2].full_name)
138
+ assert_equal('Class#new', methods[3].full_name)
139
+ assert_equal('<Class::Object>#allocate', methods[4].full_name)
140
+ assert_equal('Object#initialize', methods[5].full_name)
141
+
142
+ # Check times
143
+ assert_in_delta(0.2, methods[0].total_time, 0.01)
144
+ assert_in_delta(0, methods[0].wait_time, 0.01)
145
+ assert_in_delta(0, methods[0].self_time, 0.01)
146
+
147
+ assert_in_delta(0.2, methods[1].total_time, 0.01)
148
+ assert_in_delta(0, methods[1].wait_time, 0.01)
149
+ assert_in_delta(0, methods[1].self_time, 0.01)
150
+
151
+ assert_in_delta(0.2, methods[2].total_time, 0.01)
152
+ assert_in_delta(0, methods[2].wait_time, 0.01)
153
+ assert_in_delta(0.2, methods[2].self_time, 0.01)
154
+
155
+ assert_in_delta(0, methods[3].total_time, 0.01)
156
+ assert_in_delta(0, methods[3].wait_time, 0.01)
157
+ assert_in_delta(0, methods[3].self_time, 0.01)
158
+
159
+ assert_in_delta(0, methods[4].total_time, 0.01)
160
+ assert_in_delta(0, methods[4].wait_time, 0.01)
161
+ assert_in_delta(0, methods[4].self_time, 0.01)
162
+
163
+ assert_in_delta(0, methods[5].total_time, 0.01)
164
+ assert_in_delta(0, methods[5].wait_time, 0.01)
165
+ assert_in_delta(0, methods[5].self_time, 0.01)
166
+ end
167
+
168
+ def test_ignore_method_in_instance_methods
169
+ RubyProf::ignore_methods = [ 'Array#each' ]
170
+ result = RubyProf.profile do
171
+ [1].each do |i|
172
+ C1.new.hello
173
+ end
174
+ end
175
+
176
+ # Methods called
177
+ # BasicTest#test_ignore_method_in_instance_methods
178
+ # Array#each -- ignored!
179
+ # Class.new
180
+ # Class:Object#allocate
181
+ # for Object#initialize
182
+ # C1#hello
183
+ # Kernel#sleep
184
+
185
+ methods = result.threads.values.first.sort.reverse
186
+ assert_equal(6, methods.length)
187
+
188
+ assert_equal('BasicTest#test_ignore_method_in_instance_methods', methods[0].full_name)
189
+ assert_equal('C1#hello', methods[1].full_name)
190
+ ensure
191
+ RubyProf::ignore_methods = []
192
+ end
193
+
194
+ def test_module_methods
195
+ result = RubyProf.profile do
196
+ C2.hello
197
+ end
198
+
199
+ # Methods:
200
+ # BasicTest#test_module_methods
201
+ # M1#hello
202
+ # Kernel#sleep
203
+
204
+ methods = result.threads.values.first.sort.reverse
205
+ assert_equal(3, methods.length)
206
+
207
+ assert_equal('BasicTest#test_module_methods', methods[0].full_name)
208
+ assert_equal('M1#hello', methods[1].full_name)
209
+ assert_equal('Kernel#sleep', methods[2].full_name)
210
+
211
+ # Check times
212
+ assert_in_delta(0.3, methods[0].total_time, 0.01)
213
+ assert_in_delta(0, methods[0].wait_time, 0.01)
214
+ assert_in_delta(0, methods[0].self_time, 0.01)
215
+
216
+ assert_in_delta(0.3, methods[1].total_time, 0.01)
217
+ assert_in_delta(0, methods[1].wait_time, 0.01)
218
+ assert_in_delta(0, methods[1].self_time, 0.01)
219
+
220
+ assert_in_delta(0.3, methods[2].total_time, 0.01)
221
+ assert_in_delta(0, methods[2].wait_time, 0.01)
222
+ assert_in_delta(0.3, methods[2].self_time, 0.01)
223
+ end
224
+
225
+ def test_module_instance_methods
226
+ result = RubyProf.profile do
227
+ C2.new.hello
228
+ end
229
+
230
+ # Methods:
231
+ # BasicTest#test_module_instance_methods
232
+ # Class#new
233
+ # <Class::Object>#allocate
234
+ # Object#initialize
235
+ # M1#hello
236
+ # Kernel#sleep
237
+
238
+ methods = result.threads.values.first.sort.reverse
239
+ assert_equal(6, methods.length)
240
+
241
+ assert_equal('BasicTest#test_module_instance_methods', methods[0].full_name)
242
+ assert_equal('M1#hello', methods[1].full_name)
243
+ assert_equal('Kernel#sleep', methods[2].full_name)
244
+ assert_equal('Class#new', methods[3].full_name)
245
+ assert_equal('<Class::Object>#allocate', methods[4].full_name)
246
+ assert_equal('Object#initialize', methods[5].full_name)
247
+
248
+ # Check times
249
+ assert_in_delta(0.3, methods[0].total_time, 0.01)
250
+ assert_in_delta(0, methods[0].wait_time, 0.01)
251
+ assert_in_delta(0, methods[0].self_time, 0.01)
252
+
253
+ assert_in_delta(0.3, methods[1].total_time, 0.01)
254
+ assert_in_delta(0, methods[1].wait_time, 0.01)
255
+ assert_in_delta(0, methods[1].self_time, 0.01)
256
+
257
+ assert_in_delta(0.3, methods[2].total_time, 0.01)
258
+ assert_in_delta(0, methods[2].wait_time, 0.01)
259
+ assert_in_delta(0.3, methods[2].self_time, 0.01)
260
+
261
+ assert_in_delta(0, methods[3].total_time, 0.01)
262
+ assert_in_delta(0, methods[3].wait_time, 0.01)
263
+ assert_in_delta(0, methods[3].self_time, 0.01)
264
+
265
+ assert_in_delta(0, methods[4].total_time, 0.01)
266
+ assert_in_delta(0, methods[4].wait_time, 0.01)
267
+ assert_in_delta(0, methods[4].self_time, 0.01)
268
+
269
+ assert_in_delta(0, methods[5].total_time, 0.01)
270
+ assert_in_delta(0, methods[5].wait_time, 0.01)
271
+ assert_in_delta(0, methods[5].self_time, 0.01)
272
+ end
273
+
274
+ def test_singleton
275
+ c3 = C3.new
276
+
277
+ class << c3
278
+ def hello
279
+ end
280
+ end
281
+
282
+ result = RubyProf.profile do
283
+ c3.hello
284
+ end
285
+
286
+ methods = result.threads.values.first.sort.reverse
287
+ assert_equal(2, methods.length)
288
+
289
+ assert_equal('BasicTest#test_singleton', methods[0].full_name)
290
+ assert_equal('<Object::C3>#hello', methods[1].full_name)
291
+
292
+ assert_in_delta(0, methods[0].total_time, 0.01)
293
+ assert_in_delta(0, methods[0].wait_time, 0.01)
294
+ assert_in_delta(0, methods[0].self_time, 0.01)
295
+
296
+ assert_in_delta(0, methods[1].total_time, 0.01)
297
+ assert_in_delta(0, methods[1].wait_time, 0.01)
298
+ assert_in_delta(0, methods[1].self_time, 0.01)
299
+ end
300
+
301
+ def test_traceback
302
+ RubyProf.start
303
+ assert_raise(NoMethodError) do
304
+ RubyProf.xxx
305
+ end
306
+
307
+ RubyProf.stop
308
+ end
309
+ end