ruby-prof 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/CHANGES +54 -1
  2. data/README +134 -7
  3. data/Rakefile +40 -58
  4. data/bin/ruby-prof +21 -6
  5. data/ext/extconf.rb +13 -0
  6. data/ext/measure_allocations.h +16 -1
  7. data/ext/measure_cpu_time.h +15 -3
  8. data/ext/measure_gc_runs.h +76 -0
  9. data/ext/measure_gc_time.h +57 -0
  10. data/ext/measure_memory.h +61 -2
  11. data/ext/measure_process_time.h +13 -2
  12. data/ext/measure_wall_time.h +12 -1
  13. data/ext/mingw/Rakefile +23 -0
  14. data/ext/mingw/build.rake +38 -0
  15. data/ext/ruby_prof.c +685 -633
  16. data/ext/ruby_prof.h +188 -0
  17. data/ext/vc/ruby_prof.sln +20 -0
  18. data/ext/vc/ruby_prof.vcproj +241 -0
  19. data/ext/version.h +4 -0
  20. data/lib/ruby-prof.rb +4 -0
  21. data/lib/ruby-prof/call_info.rb +47 -0
  22. data/lib/ruby-prof/call_tree_printer.rb +9 -1
  23. data/lib/ruby-prof/graph_html_printer.rb +6 -5
  24. data/lib/ruby-prof/graph_printer.rb +3 -2
  25. data/lib/ruby-prof/method_info.rb +85 -0
  26. data/lib/ruby-prof/task.rb +1 -2
  27. data/lib/ruby-prof/test.rb +148 -0
  28. data/rails/environment/profile.rb +24 -0
  29. data/rails/example/example_test.rb +9 -0
  30. data/rails/profile_test_helper.rb +21 -0
  31. data/test/basic_test.rb +173 -80
  32. data/test/duplicate_names_test.rb +2 -3
  33. data/test/exceptions_test.rb +15 -0
  34. data/test/exclude_threads_test.rb +54 -0
  35. data/test/line_number_test.rb +18 -14
  36. data/test/measurement_test.rb +121 -0
  37. data/test/module_test.rb +5 -8
  38. data/test/no_method_class_test.rb +4 -5
  39. data/test/prime.rb +3 -5
  40. data/test/prime_test.rb +1 -12
  41. data/test/printers_test.rb +10 -13
  42. data/test/profile_unit_test.rb +10 -12
  43. data/test/recursive_test.rb +202 -92
  44. data/test/singleton_test.rb +1 -2
  45. data/test/stack_test.rb +138 -0
  46. data/test/start_stop_test.rb +95 -0
  47. data/test/test_suite.rb +7 -3
  48. data/test/thread_test.rb +111 -87
  49. data/test/unique_call_path_test.rb +206 -0
  50. metadata +40 -42
  51. data/ext/extconf.rb.rej +0 -13
  52. data/lib/ruby-prof/call_tree_printer.rb.rej +0 -27
  53. data/lib/ruby-prof/profile_test_case.rb +0 -80
  54. data/rails_plugin/ruby-prof/init.rb +0 -8
  55. data/rails_plugin/ruby-prof/lib/profiling.rb +0 -57
  56. data/test/measure_mode_test.rb +0 -79
  57. data/test/prime1.rb +0 -17
  58. data/test/prime2.rb +0 -26
  59. data/test/prime3.rb +0 -17
  60. data/test/start_test.rb +0 -24
  61. data/test/test_helper.rb +0 -55
  62. data/test/timing_test.rb +0 -133
data/CHANGES CHANGED
@@ -1,4 +1,57 @@
1
- 0.6.0 (2007-02-03)
1
+ 0.7.0 (2008-11-04)
2
+ ========================
3
+
4
+ Features
5
+ --------
6
+ * Added two new methods - RubyProf.resume and RubyProf.pause.
7
+ RubyProf.resume takes an optional block, which ensures that
8
+ RubyProf.pause is called. For example:
9
+
10
+ 10.times do |i|
11
+ RubyProf.resume do
12
+ # Some long process
13
+ end
14
+ end
15
+
16
+ result = RubyProf.stop
17
+
18
+ * Added support for profiling tests that use Ruby's built-in
19
+ unit test framework (ie, test derived from
20
+ Test::Unit::TestCase). To enable profiling simply add
21
+ the following line of code to your test class:
22
+
23
+ include RubyProf::Test
24
+
25
+ By default, profiling results are written to the current
26
+ processes working directory. To change this, or other
27
+ profiling options, simply modify the PROFILE_OPTIONS hash
28
+ table as needed.
29
+
30
+ * Used the new support for profiling test cases to revamp
31
+ the way that Rails profiling works. For more information
32
+ please refer to RubyProf's documentation.
33
+
34
+ * Keep track of call stack for each method to enable more
35
+ powerful profile visualizations in Integrated Development
36
+ Environments (Hin Boean, work supported by CodeGear).
37
+
38
+ * Expose measurements to Ruby (Jeremy Kemper).
39
+
40
+ * Add support for additional memory measurements modes in Ruby 1.9 (Jeremy Kemper).
41
+
42
+ * Add support for Lloyd Hilaiel's Ruby patch for measuring total heap size.
43
+ See http://lloydforge.org/projects/ruby. (Jeremy Kemper).
44
+
45
+
46
+ Fixes
47
+ -------
48
+ * RubyProf.profile no longer crashes if an exception is
49
+ thrown during a profiling run.
50
+
51
+ * Measure memory in fractional kilobytes rather than rounding down (Jeremy Kemper)
52
+
53
+
54
+ 0.6.0 (2008-02-03)
2
55
  ========================
3
56
 
4
57
  ruby-prof 0.6.0 adds support for Ruby 1.9 and memory profiling.
data/README CHANGED
@@ -41,12 +41,14 @@ ruby-prof is also available as a tarred gzip archive and zip archive.
41
41
 
42
42
  There are three ways of running ruby-prof.
43
43
 
44
+
44
45
  === ruby-prof executable
45
46
 
46
47
  The first is to use ruby-prof to run the Ruby program
47
48
  you want to profile. For more information refer to
48
49
  the ruby-prof documentation[link:files/bin/ruby-prof.html].
49
50
 
51
+
50
52
  === ruby-prof API
51
53
 
52
54
  The second way is to use the ruby-prof API to profile
@@ -81,7 +83,36 @@ to profile:
81
83
  printer = RubyProf::GraphPrinter.new(result)
82
84
  printer.print(STDOUT, 0)
83
85
 
86
+ Starting with the 0.6.1 release, ruby-prof also supports pausing and resuming
87
+ profiling runs.
88
+
89
+ require 'ruby-prof'
90
+
91
+ # Profile the code
92
+ RubyProf.start
93
+ [code to profile]
94
+ RubyProf.pause
95
+ [other code]
96
+ RubyProf.resume
97
+ [code to profile]
98
+ result = RubyProf.stop
99
+
100
+ Note that resume will automatically call start if a profiling run
101
+ has not yet started. In addition, resume can also take a block:
102
+
103
+ require 'ruby-prof'
104
+
105
+ # Profile the code
106
+ RubyProf.resume do
107
+ [code to profile]
108
+ end
109
+
110
+ data = RubyProf.stop
84
111
 
112
+ With this usage, resume will automatically call pause at the
113
+ end of the block.
114
+
115
+
85
116
  === require unprof
86
117
 
87
118
  The third way of using ruby-prof is by requiring unprof.rb:
@@ -93,7 +124,82 @@ using a flat profile report.
93
124
 
94
125
  This method is provided for backwards compatibility. Using
95
126
  {ruby-prof}[link:files/bin/ruby-prof.html] provides more flexibility.
127
+
128
+
129
+ == Profiling Tests
130
+
131
+ Starting with the 0.6.1 release, ruby-prof supports profiling tests cases
132
+ written using Ruby's built-in unit test framework (ie, test derived from
133
+ Test::Unit::TestCase). To enable profiling simply add the following line
134
+ of code to your test class:
96
135
 
136
+ include RubyProf::Test
137
+
138
+ Each test method is profiled separately. ruby-prof will run each test method
139
+ once as a warmup and then ten additional times to gather profile data.
140
+ Note that the profile data will *not* include the class's setup or
141
+ teardown methods.
142
+
143
+ Separate reports are generated for each method and saved, by default,
144
+ in the test process's working directory. To change this, or other profiling
145
+ options, modify your test class's PROFILE_OPTIONS hash table. To globally
146
+ change test profiling options, modify RubyProf::Test::PROFILE_OPTIONS.
147
+
148
+
149
+ == Profiling Rails
150
+
151
+ To profile a Rails application it is vital to run it using production like
152
+ settings (cache classes, cache view lookups, etc.). Otherwise, Rail's
153
+ dependency loading code will overwhelm any time spent in the application
154
+ itself (our tests show that Rails dependency loading causes a roughly 6x
155
+ slowdown). The best way to do this is create a new Rails environment,
156
+ profile.rb.
157
+
158
+ So to profile Rails:
159
+
160
+ 1. Create a new profile.rb environment - or simply copy the example file
161
+ in ruby-prof/rails/environment/profile.rb
162
+
163
+ 2. Copy the file:
164
+
165
+ ruby-prof/rails/profile_test_helper.rb
166
+
167
+ To:
168
+
169
+ your_rails_app/test/profile_test_helper.rb
170
+
171
+ 3. Create a new test directory for profiling:
172
+
173
+ your_rails_app/test/profile
174
+
175
+
176
+ 4. Write unit, functional or integration tests specifically designed
177
+ to profile some part of your Rails application. At the top
178
+ of each test, replace this line:
179
+
180
+ require File.dirname(__FILE__) + '/../test_helper'
181
+
182
+ With:
183
+
184
+ require File.dirname(__FILE__) + '/../profile_test_helper'
185
+
186
+ For example:
187
+
188
+ require File.dirname(__FILE__) + '/../profile_test_helper'
189
+
190
+ class ExampleTest < Test::Unit::TestCase
191
+ include RubyProf::Test
192
+ fixtures ....
193
+
194
+ def test_stuff
195
+ puts "Test method"
196
+ end
197
+ end
198
+
199
+ 5. Now run your tests. Results will be written to:
200
+
201
+ your_rails_app/tmp/profile
202
+
97
203
 
98
204
  == Reports
99
205
 
@@ -133,6 +239,7 @@ by KCachegrind. Call graph support was generously donated by Carl Shimer.
133
239
  More information about the format can be found at
134
240
  the {KCachegrind}[link:http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindCalltreeFormat] site.
135
241
 
242
+
136
243
  == Printers
137
244
 
138
245
  Reports are created by printers. Supported printers include:
@@ -160,11 +267,14 @@ information please see the documentation for the different printers.
160
267
  Depending on the mode and platform, ruby-prof can measure various
161
268
  aspects of a Ruby program. Supported measurements include:
162
269
 
163
- * process time
164
- * wall time
165
- * cpu time
166
- * object allocations
167
- * memory usage
270
+ * process time (RubyProf::PROCESS_TIME)
271
+ * wall time (RubyProf::WALL_TIME)
272
+ * cpu time (RubyProf::CPU_TIME)
273
+ * object allocations (RubyProf::ALLOCATIONS)
274
+ * memory usage (RubyProf::MEMORY)
275
+ * garbage collections runs (RubyProf::GC_RUNS)
276
+ * garbage collection time (RubyProf::GC_TIME)
277
+
168
278
 
169
279
  Process time measures the time used by a process between any two moments.
170
280
  It is unaffected by other processes concurrently running
@@ -182,14 +292,24 @@ This mode is only supported on Pentium or PowerPC platforms.
182
292
 
183
293
  Object allocation reports show how many objects each method in
184
294
  a program allocates. This support was added by Sylvain Joyeux
185
- and requires a patched Ruby interpreter. For more information, see:
295
+ and requires a patched Ruby interpreter. For more information and
296
+ the patch, please see:
186
297
  http://rubyforge.org/tracker/index.php?func=detail&aid=11497&group_id=426&atid=1700
187
298
 
188
299
  Memory usage reports show how much memory each method in a program
189
300
  uses. This support was added by Alexander Dymo and requires a
190
301
  patched Ruby interpreter. For more information, see:
191
- http://rubyforge.org/tracker/index.php?func=detail&aid=17676&group_id=1814&atid=7062.
302
+ http://rubyforge.org/tracker/index.php?func=detail&aid=17676&group_id=1814&atid=7062
192
303
 
304
+ Garbage collection runs report how many times Ruby's garbage collector
305
+ is invoked during a profiling session. This support was added by Jeremy
306
+ Kemper and requires a patched Ruby interpreter. For more information, see:
307
+ http://rubyforge.org/tracker/index.php?func=detail&aid=17676&group_id=1814&atid=7062
308
+
309
+ Garbage collection time reports how much time is spent in Ruby's garbage collector
310
+ during a profiling session. This support was added by Jeremy Kemper
311
+ and requires a patched Ruby interpreter. For more information, see:
312
+ http://rubyforge.org/tracker/index.php?func=detail&aid=17676&group_id=1814&atid=7062
193
313
 
194
314
  To set the measurement:
195
315
 
@@ -198,6 +318,8 @@ To set the measurement:
198
318
  * RubyProf.measure_mode = RubyProf::CPU_TIME
199
319
  * RubyProf.measure_mode = RubyProf::ALLOCATIONS
200
320
  * RubyProf.measure_mode = RubyProf::MEMORY
321
+ * RubyProf.measure_mode = RubyProf::GC_RUNS
322
+ * RubyProf.measure_mode = RubyProf::GC_TIME
201
323
 
202
324
  The default value is RubyProf::PROCESS_TIME.
203
325
 
@@ -208,6 +330,9 @@ environment variable:
208
330
  * export RUBY_PROF_MEASURE_MODE=wall
209
331
  * export RUBY_PROF_MEASURE_MODE=cpu
210
332
  * export RUBY_PROF_MEASURE_MODE=allocations
333
+ * export RUBY_PROF_MEASURE_MODE=memory
334
+ * export RUBY_PROF_MEASURE_MODE=gc_runs
335
+ * export RUBY_PROF_MEASURE_MODE=gc_time
211
336
 
212
337
  Note that these values have changed since ruby-prof-0.3.0.
213
338
 
@@ -271,6 +396,7 @@ However, the self time values for recursive calls should always
271
396
  be accurate. It is also believed that the total times are
272
397
  accurate, but these should be carefully analyzed to verify their veracity.
273
398
 
399
+
274
400
  == Multi-threaded Applications
275
401
 
276
402
  Unfortunately, Ruby does not provide an internal api
@@ -294,6 +420,7 @@ profiled. Most programs will run approximately twice as slow
294
420
  while highly recursive programs (like the fibonacci series test)
295
421
  will run three times slower.
296
422
 
423
+
297
424
  == Windows Binary
298
425
 
299
426
  The Windows binary is built with the latest version of MinGW. The source
data/Rakefile CHANGED
@@ -1,25 +1,33 @@
1
1
  require 'rubygems'
2
- require 'date'
3
2
  require 'rake/gempackagetask'
4
3
  require 'rake/rdoctask'
4
+ require 'rake/testtask'
5
5
  require 'date'
6
6
 
7
- SO_NAME = "ruby_prof.so"
7
+ # ------- Version ----
8
+ # Read version from header file
9
+ version_header = File.read('ext/version.h')
10
+ match = version_header.match(/RUBY_PROF_VERSION\s*["](\d.+)["]/)
11
+ raise(RuntimeError, "Could not determine RUBY_PROF_VERSION") if not match
12
+ RUBY_PROF_VERSION = match[1]
13
+
8
14
 
9
15
  # ------- Default Package ----------
10
- RUBY_PROF_VERSION = "0.6.0"
11
-
12
16
  FILES = FileList[
13
17
  'Rakefile',
14
18
  'README',
15
19
  'LICENSE',
16
20
  'CHANGES',
17
21
  'bin/*',
18
- 'lib/**/*',
19
- 'rails_plugin/**/*',
22
+ 'doc/**/*',
20
23
  'examples/*',
21
24
  'ext/*',
22
- 'doc/**/*',
25
+ 'ext/mingw/Rakefile',
26
+ 'ext/mingw/build.rake',
27
+ 'ext/vc/*.sln',
28
+ 'ext/vc/*.vcproj',
29
+ 'lib/**/*',
30
+ 'rails/**/*',
23
31
  'test/*'
24
32
  ]
25
33
 
@@ -57,56 +65,31 @@ EOF
57
65
 
58
66
  # rdoc
59
67
  spec.has_rdoc = true
60
- spec.rdoc_options << "--title" << "ruby-prof"
61
- # Show source inline with line numbers
62
- spec.rdoc_options << "--inline-source" << "--line-numbers"
63
- # Make the readme file the start page for the generated html
64
- spec.rdoc_options << '--main' << 'README'
65
- spec.extra_rdoc_files = ['bin/ruby-prof',
66
- 'ext/ruby_prof.c',
67
- 'examples/flat.txt',
68
- 'examples/graph.txt',
69
- 'examples/graph.html',
70
- 'README',
71
- 'LICENSE']
72
-
73
68
  end
74
69
 
75
70
  # Rake task to build the default package
76
71
  Rake::GemPackageTask.new(default_spec) do |pkg|
77
72
  pkg.need_tar = true
78
- pkg.need_zip = true
73
+ #pkg.need_zip = true
79
74
  end
80
75
 
81
76
 
82
77
  # ------- Windows Package ----------
83
- # Windows specification
84
- win_spec = default_spec.clone
85
- win_spec.extensions = []
86
- win_spec.platform = Gem::Platform::CURRENT
87
- win_spec.files += ["lib/#{SO_NAME}"]
88
-
89
- desc "Create Windows Gem"
90
- task :create_win32_gem do
91
- # Copy the win32 extension built by MingW - easier to install
92
- # since there are no dependencies of msvcr80.dll
93
- current_dir = File.expand_path(File.dirname(__FILE__))
94
- source = File.join(current_dir, "mingw", SO_NAME)
95
- target = File.join(current_dir, "lib", SO_NAME)
96
- cp(source, target)
97
-
98
- # Create the gem, then move it to pkg
99
- Gem::Builder.new(win_spec).build
100
- gem_file = "#{win_spec.name}-#{win_spec.version}-#{win_spec.platform}.gem"
101
- mv(gem_file, "pkg/#{gem_file}")
102
-
103
- # Remove win extension from top level directory
104
- rm(target)
78
+ if RUBY_PLATFORM.match(/win32/)
79
+ binaries = (FileList['ext/mingw/*.so',
80
+ 'ext/mingw/*.dll*'])
81
+
82
+ # Windows specification
83
+ win_spec = default_spec.clone
84
+ win_spec.extensions = ['ext/mingw/Rakefile']
85
+ win_spec.platform = Gem::Platform::CURRENT
86
+ win_spec.files += binaries.to_a
87
+
88
+ # Rake task to build the windows package
89
+ Rake::GemPackageTask.new(win_spec) do |pkg|
90
+ end
105
91
  end
106
92
 
107
-
108
- task :package => :create_win32_gem
109
-
110
93
  # --------- RDoc Documentation ------
111
94
  desc "Generate rdoc documentation"
112
95
  Rake::RDocTask.new("rdoc") do |rdoc|
@@ -122,20 +105,19 @@ Rake::RDocTask.new("rdoc") do |rdoc|
122
105
  'examples/graph.txt',
123
106
  'examples/graph.html',
124
107
  'lib/**/*.rb',
125
- 'ext/**/ruby_prof.c',
108
+ 'ext/ruby_prof.c',
109
+ 'ext/version.h',
110
+ 'ext/measure_*.h',
126
111
  'README',
127
112
  'LICENSE')
128
113
  end
129
114
 
115
+ task :default => :package
130
116
 
131
- # --------- Publish to RubyForge ----------------
132
- desc "Publish ruby-prof to RubyForge."
133
- task :publish do
134
- require 'rake/contrib/sshpublisher'
135
-
136
- # Get ruby-prof path
137
- ruby_prof_path = File.expand_path(File.dirname(__FILE__))
138
-
139
- publisher = Rake::SshDirPublisher.new("cfis@rubyforge.org",
140
- "/var/www/gforge-projects/ruby-prof", ruby_prof_path)
141
- end
117
+ desc 'Run the ruby-prof test suite'
118
+ Rake::TestTask.new do |t|
119
+ t.libs += %w(lib ext test)
120
+ t.test_files = Dir['test/*_test.rb'] - %w(test/profile_unit_test.rb)
121
+ t.verbose = true
122
+ t.warning = true
123
+ end
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # == Usage
8
8
  #
9
- # ruby_prof [options] <script.rb> [options-for-script]
9
+ # ruby_prof [options] <script.rb> [--] [script-options]"
10
10
  #
11
11
  # Options:
12
12
  # -p, --printer=printer Select a printer:
@@ -25,6 +25,12 @@
25
25
  # (only supported on Pentium and PowerPCs).
26
26
  # allocations - Tracks object allocations
27
27
  # (requires a patched Ruby interpreter).
28
+ # memory - Tracks total memory size
29
+ # (requires a patched Ruby interpreter).
30
+ # gc_runs - Tracks number of garbage collection runs
31
+ # (requires a patched Ruby interpreter).
32
+ # gc_time - Tracks time spent doing garbage collection
33
+ # (requires a patched Ruby interpreter).
28
34
  # --replace-progname Replace $0 when loading the .rb files.
29
35
  # --specialized-instruction Turn on specialized instruction.
30
36
  # -h, --help Show help message
@@ -48,7 +54,7 @@ options.specialized_instruction = false
48
54
 
49
55
  opts = OptionParser.new do |opts|
50
56
  opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
51
- "Usage: ruby_prof [options] <script.rb> [--extra-options-for-script]"
57
+ "Usage: ruby_prof [options] <script.rb> [--] [script-options]"
52
58
 
53
59
  opts.separator ""
54
60
  opts.separator "Options:"
@@ -87,12 +93,15 @@ opts = OptionParser.new do |opts|
87
93
  end
88
94
 
89
95
  opts.on('--mode=measure_mode',
90
- [:process, :wall, :cpu, :allocations],
96
+ [:process, :wall, :cpu, :allocations, :memory, :gc_runs, :gc_time],
91
97
  'Select what ruby-prof should measure:',
92
98
  ' process - Process time (default).',
93
99
  ' wall - Wall time.',
94
100
  ' cpu - CPU time (Pentium and PowerPCs only).',
95
- ' allocations - Object allocations (requires patched Ruby interpreter).') do |measure_mode|
101
+ ' allocations - Object allocations (requires patched Ruby interpreter).',
102
+ ' memory - Allocated memory in KB (requires patched Ruby interpreter).',
103
+ ' gc_runs - Number of garbage collections (requires patched Ruby interpreter).',
104
+ ' gc_time - Time spent in garbage collection (requires patched Ruby interpreter).') do |measure_mode|
96
105
 
97
106
  case measure_mode
98
107
  when :process
@@ -103,6 +112,12 @@ opts = OptionParser.new do |opts|
103
112
  options.measure_mode = RubyProf::CPU_TIME
104
113
  when :allocations
105
114
  options.measure_mode = RubyProf::ALLOCATIONS
115
+ when :memory
116
+ options.measure_mode = RubyProf::MEMORY
117
+ when :gc_runs
118
+ options.measure_mode = RubyProf::GC_RUNS
119
+ when :gc_time
120
+ options.measure_mode = RubyProf::GC_TIME
106
121
  end
107
122
  end
108
123
 
@@ -182,11 +197,11 @@ end
182
197
  # Get the script we will execute
183
198
  script = ARGV.shift
184
199
  if options.replace_prog_name
185
- $0 = File.basename(File.expand_path(script))
200
+ $0 = File.expand_path(script)
186
201
  end
187
202
 
188
203
  # Start profiling
189
204
  RubyProf.start
190
205
 
191
206
  # Load the script
192
- load script
207
+ load script