ruby-prof 0.8.1-x86-mingw32

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 (64) hide show
  1. data/CHANGES +221 -0
  2. data/LICENSE +23 -0
  3. data/README +432 -0
  4. data/Rakefile +159 -0
  5. data/bin/ruby-prof +224 -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/ruby_prof/measure_allocations.h +58 -0
  10. data/ext/ruby_prof/measure_cpu_time.h +152 -0
  11. data/ext/ruby_prof/measure_gc_runs.h +76 -0
  12. data/ext/ruby_prof/measure_gc_time.h +57 -0
  13. data/ext/ruby_prof/measure_memory.h +101 -0
  14. data/ext/ruby_prof/measure_process_time.h +52 -0
  15. data/ext/ruby_prof/measure_wall_time.h +53 -0
  16. data/ext/ruby_prof/mingw/Rakefile +23 -0
  17. data/ext/ruby_prof/mingw/build.rake +38 -0
  18. data/ext/ruby_prof/ruby_prof.c +1747 -0
  19. data/ext/ruby_prof/ruby_prof.h +188 -0
  20. data/ext/ruby_prof/version.h +4 -0
  21. data/lib/1.8/ruby_prof.so +0 -0
  22. data/lib/1.9/ruby_prof.so +0 -0
  23. data/lib/ruby-prof.rb +56 -0
  24. data/lib/ruby-prof/abstract_printer.rb +41 -0
  25. data/lib/ruby-prof/aggregate_call_info.rb +62 -0
  26. data/lib/ruby-prof/call_info.rb +47 -0
  27. data/lib/ruby-prof/call_tree_printer.rb +84 -0
  28. data/lib/ruby-prof/flat_printer.rb +78 -0
  29. data/lib/ruby-prof/flat_printer_with_line_numbers.rb +72 -0
  30. data/lib/ruby-prof/graph_html_printer.rb +256 -0
  31. data/lib/ruby-prof/graph_printer.rb +157 -0
  32. data/lib/ruby-prof/method_info.rb +111 -0
  33. data/lib/ruby-prof/symbol_to_proc.rb +8 -0
  34. data/lib/ruby-prof/task.rb +146 -0
  35. data/lib/ruby-prof/test.rb +148 -0
  36. data/lib/unprof.rb +8 -0
  37. data/rails/environment/profile.rb +24 -0
  38. data/rails/example/example_test.rb +9 -0
  39. data/rails/profile_test_helper.rb +21 -0
  40. data/test/aggregate_test.rb +121 -0
  41. data/test/basic_test.rb +290 -0
  42. data/test/current_failures_windows +8 -0
  43. data/test/do_nothing.rb +0 -0
  44. data/test/duplicate_names_test.rb +32 -0
  45. data/test/enumerable_test.rb +16 -0
  46. data/test/exceptions_test.rb +15 -0
  47. data/test/exclude_threads_test.rb +54 -0
  48. data/test/exec_test.rb +14 -0
  49. data/test/line_number_test.rb +73 -0
  50. data/test/measurement_test.rb +121 -0
  51. data/test/module_test.rb +54 -0
  52. data/test/no_method_class_test.rb +13 -0
  53. data/test/prime.rb +58 -0
  54. data/test/prime_test.rb +13 -0
  55. data/test/printers_test.rb +130 -0
  56. data/test/recursive_test.rb +275 -0
  57. data/test/ruby-prof-bin +20 -0
  58. data/test/singleton_test.rb +37 -0
  59. data/test/stack_test.rb +138 -0
  60. data/test/start_stop_test.rb +95 -0
  61. data/test/test_suite.rb +23 -0
  62. data/test/thread_test.rb +173 -0
  63. data/test/unique_call_path_test.rb +225 -0
  64. metadata +143 -0
@@ -0,0 +1,111 @@
1
+ module RubyProf
2
+ class MethodInfo
3
+ include Comparable
4
+
5
+ def <=>(other)
6
+ if self.total_time < other.total_time
7
+ -1
8
+ elsif self.total_time > other.total_time
9
+ 1
10
+ elsif self.min_depth < other.min_depth
11
+ 1
12
+ elsif self.min_depth > other.min_depth
13
+ -1
14
+ else
15
+ -1 * (self.full_name <=> other.full_name)
16
+ end
17
+ end
18
+
19
+ def called
20
+ @called ||= begin
21
+ call_infos.inject(0) do |sum, call_info|
22
+ sum += call_info.called
23
+ end
24
+ end
25
+ end
26
+
27
+ def total_time
28
+ @total_time ||= begin
29
+ call_infos.inject(0) do |sum, call_info|
30
+ sum += call_info.total_time
31
+ end
32
+ end
33
+ end
34
+
35
+ def self_time
36
+ @self_time ||= begin
37
+ call_infos.inject(0) do |sum, call_info|
38
+ sum += call_info.self_time
39
+ end
40
+ end
41
+ end
42
+
43
+ def wait_time
44
+ @wait_time ||= begin
45
+ call_infos.inject(0) do |sum, call_info|
46
+ sum += call_info.wait_time
47
+ end
48
+ end
49
+ end
50
+
51
+ def children_time
52
+ @children_time ||= begin
53
+ call_infos.inject(0) do |sum, call_info|
54
+ sum += call_info.children_time
55
+ end
56
+ end
57
+ end
58
+
59
+ def min_depth
60
+ @min_depth ||= call_infos.map do |call_info|
61
+ call_info.depth
62
+ end.min
63
+ end
64
+
65
+ def root?
66
+ @root ||= begin
67
+ call_infos.find do |call_info|
68
+ not call_info.root?
69
+ end.nil?
70
+ end
71
+ end
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
+ # Group call info's based on their parents
83
+ groups = self.call_infos.inject(Hash.new) do |hash, call_info|
84
+ key = call_info.parent ? call_info.parent.target : self
85
+ (hash[key] ||= []) << call_info
86
+ hash
87
+ end
88
+
89
+ groups.map do |key, value|
90
+ AggregateCallInfo.new(value)
91
+ end
92
+ end
93
+
94
+ def aggregate_children
95
+ # Group call info's based on their targets
96
+ groups = self.children.inject(Hash.new) do |hash, call_info|
97
+ key = call_info.target
98
+ (hash[key] ||= []) << call_info
99
+ hash
100
+ end
101
+
102
+ groups.map do |key, value|
103
+ AggregateCallInfo.new(value)
104
+ end
105
+ end
106
+
107
+ def to_s
108
+ full_name
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,8 @@
1
+ unless (:a.respond_to?(:to_proc))
2
+ class Symbol
3
+ def to_proc
4
+ proc {|stuff| stuff.send(self)}
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'fileutils'
6
+
7
+ module RubyProf
8
+
9
+ # Define a task library for profiling unit tests with ruby-prof.
10
+ #
11
+ # All of the options provided by
12
+ # the Rake:TestTask are supported except the loader
13
+ # which is set to ruby-prof. For detailed information
14
+ # please refer to the Rake:TestTask documentation.
15
+ #
16
+ # ruby-prof specific options include:
17
+ #
18
+ # output_dir - For each file specified an output
19
+ # file with profile information will be
20
+ # written to the output directory.
21
+ # By default, the output directory is
22
+ # called "profile" and is created underneath
23
+ # the current working directory.
24
+ #
25
+ # printer - Specifies the output printer. Valid values include
26
+ # :flat, :graph, :graph_html and :call_tree.
27
+ #
28
+ # min_percent - Methods that take less than the specified percent
29
+ # will not be written out.
30
+ #
31
+ # Example:
32
+ #
33
+ # require 'ruby-prof/task'
34
+ #
35
+ # RubyProf::ProfileTask.new do |t|
36
+ # t.test_files = FileList['test/test*.rb']
37
+ # t.output_dir = "c:/temp"
38
+ # t.printer = :graph
39
+ # t.min_percent = 10
40
+ # end
41
+ #
42
+ # If rake is invoked with a "TEST=filename" command line option,
43
+ # then the list of test files will be overridden to include only the
44
+ # filename specified on the command line. This provides an easy way
45
+ # to run just one test.
46
+ #
47
+ # If rake is invoked with a "TESTOPTS=options" command line option,
48
+ # then the given options are passed to the test process after a
49
+ # '--'. This allows Test::Unit options to be passed to the test
50
+ # suite.
51
+ #
52
+ # Examples:
53
+ #
54
+ # rake profile # run tests normally
55
+ # rake profile TEST=just_one_file.rb # run just one test file.
56
+ # rake profile TESTOPTS="-v" # run in verbose mode
57
+ # rake profile TESTOPTS="--runner=fox" # use the fox test runner
58
+
59
+ class ProfileTask < Rake::TestTask
60
+ attr_accessor :output_dir
61
+ attr_accessor :min_percent
62
+ attr_accessor :printer
63
+
64
+ def initialize(name = :profile)
65
+ super(name)
66
+ end
67
+
68
+ # Create the tasks defined by this task lib.
69
+ def define
70
+ lib_path = @libs.join(File::PATH_SEPARATOR)
71
+ desc "Profile" + (@name==:profile ? "" : " for #{@name}")
72
+
73
+ task @name do
74
+ create_output_directory
75
+
76
+ @ruby_opts.unshift( "-I#{lib_path}" )
77
+ @ruby_opts.unshift( "-w" ) if @warning
78
+ @ruby_opts.push("-S ruby-prof")
79
+ @ruby_opts.push("--printer #{@printer}")
80
+ @ruby_opts.push("--min_percent #{@min_percent}")
81
+
82
+ file_list.each do |file_path|
83
+ run_script(file_path)
84
+ end
85
+ end
86
+ self
87
+ end
88
+
89
+ # Run script
90
+ def run_script(script_path)
91
+ run_code = ''
92
+ RakeFileUtils.verbose(@verbose) do
93
+ file_name = File.basename(script_path, File.extname(script_path))
94
+ case @printer
95
+ when :flat, :graph, :call_tree
96
+ file_name += ".txt"
97
+ when :graph_html
98
+ file_name += ".html"
99
+ else
100
+ file_name += ".txt"
101
+ end
102
+
103
+ output_file_path = File.join(output_directory, file_name)
104
+
105
+ command_line = @ruby_opts.join(" ") +
106
+ " --file=" + output_file_path +
107
+ " " + script_path
108
+
109
+ puts "ruby " + command_line
110
+ # We have to catch the exeption to continue on. However,
111
+ # the error message will have been output to STDERR
112
+ # already by the time we get here so we don't have to
113
+ # do that again
114
+ begin
115
+ ruby command_line
116
+ rescue => e
117
+ STDOUT << e << "\n"
118
+ STDOUT.flush
119
+ end
120
+ puts ""
121
+ puts ""
122
+ end
123
+ end
124
+
125
+ def output_directory
126
+ File.expand_path(@output_dir)
127
+ end
128
+
129
+ def create_output_directory
130
+ if not File.exist?(output_directory)
131
+ Dir.mkdir(output_directory)
132
+ end
133
+ end
134
+
135
+ def clean_output_directory
136
+ if File.exist?(output_directory)
137
+ files = Dir.glob(output_directory + '/*')
138
+ FileUtils.rm(files)
139
+ end
140
+ end
141
+
142
+ def option_list # :nodoc:
143
+ ENV['OPTIONS'] || @options.join(" ") || ""
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,148 @@
1
+ # Now load ruby-prof and away we go
2
+ require 'fileutils'
3
+ require 'ruby-prof'
4
+ require 'benchmark'
5
+
6
+ module RubyProf
7
+ module Test
8
+ PROFILE_OPTIONS = {
9
+ :measure_modes => [RubyProf::PROCESS_TIME],
10
+ :count => 10,
11
+ :printers => [RubyProf::FlatPrinter, RubyProf::GraphHtmlPrinter],
12
+ :min_percent => 0.05,
13
+ :output_dir => Dir.pwd }
14
+
15
+ def output_dir
16
+ PROFILE_OPTIONS[:output_dir]
17
+ end
18
+
19
+ def run(result)
20
+ return if @method_name.to_s == "default_test"
21
+
22
+ yield(self.class::STARTED, name)
23
+ @_result = result
24
+ run_warmup
25
+ PROFILE_OPTIONS[:measure_modes].each do |measure_mode|
26
+ data = run_profile(measure_mode)
27
+ report_profile(data, measure_mode)
28
+ result.add_run
29
+ end
30
+ yield(self.class::FINISHED, name)
31
+ end
32
+
33
+ def run_test
34
+ begin
35
+ setup
36
+ yield
37
+ rescue ::Test::Unit::AssertionFailedError => e
38
+ add_failure(e.message, e.backtrace)
39
+ rescue StandardError, ScriptError
40
+ add_error($!)
41
+ ensure
42
+ begin
43
+ teardown
44
+ rescue ::Test::Unit::AssertionFailedError => e
45
+ add_failure(e.message, e.backtrace)
46
+ rescue StandardError, ScriptError
47
+ add_error($!)
48
+ end
49
+ end
50
+ end
51
+
52
+ def run_warmup
53
+ print "\n#{self.class.name}##{method_name}"
54
+
55
+ run_test do
56
+ bench = Benchmark.realtime do
57
+ __send__(@method_name)
58
+ end
59
+ puts " (%.2fs warmup)" % bench
60
+ end
61
+ end
62
+
63
+ def run_profile(measure_mode)
64
+ RubyProf.measure_mode = measure_mode
65
+
66
+ print ' '
67
+ PROFILE_OPTIONS[:count].times do |i|
68
+ run_test do
69
+ begin
70
+ print '.'
71
+ $stdout.flush
72
+ GC.disable
73
+
74
+ RubyProf.resume do
75
+ __send__(@method_name)
76
+ end
77
+ ensure
78
+ GC.enable
79
+ end
80
+ end
81
+ end
82
+
83
+ data = RubyProf.stop
84
+ bench = data.threads.values.inject(0) do |total, method_infos|
85
+ top = method_infos.max
86
+ total += top.total_time
87
+ total
88
+ end
89
+
90
+ puts "\n #{measure_mode_name(measure_mode)}: #{format_profile_total(bench, measure_mode)}\n"
91
+
92
+ data
93
+ end
94
+
95
+ def format_profile_total(total, measure_mode)
96
+ case measure_mode
97
+ when RubyProf::PROCESS_TIME, RubyProf::WALL_TIME
98
+ "%.2f seconds" % total
99
+ when RubyProf::MEMORY
100
+ "%.2f kilobytes" % total
101
+ when RubyProf::ALLOCATIONS
102
+ "%d allocations" % total
103
+ else
104
+ "%.2f #{measure_mode}"
105
+ end
106
+ end
107
+
108
+ def report_profile(data, measure_mode)
109
+ PROFILE_OPTIONS[:printers].each do |printer_klass|
110
+ printer = printer_klass.new(data)
111
+
112
+ # Makes sure the output directory exits
113
+ FileUtils.mkdir_p(output_dir)
114
+
115
+ # Open the file
116
+ file_name = report_filename(printer, measure_mode)
117
+
118
+ File.open(file_name, 'wb') do |file|
119
+ printer.print(file, PROFILE_OPTIONS)
120
+ end
121
+ end
122
+ end
123
+
124
+ # The report filename is test_name + measure_mode + report_type
125
+ def report_filename(printer, measure_mode)
126
+ suffix =
127
+ case printer
128
+ when RubyProf::FlatPrinter; 'flat.txt'
129
+ when RubyProf::GraphPrinter; 'graph.txt'
130
+ when RubyProf::GraphHtmlPrinter; 'graph.html'
131
+ when RubyProf::CallTreePrinter; 'tree.txt'
132
+ else printer.to_s.downcase
133
+ end
134
+
135
+ "#{output_dir}/#{method_name}_#{measure_mode_name(measure_mode)}_#{suffix}"
136
+ end
137
+
138
+ def measure_mode_name(measure_mode)
139
+ case measure_mode
140
+ when RubyProf::PROCESS_TIME; 'process_time'
141
+ when RubyProf::WALL_TIME; 'wall_time'
142
+ when RubyProf::MEMORY; 'memory'
143
+ when RubyProf::ALLOCATIONS; 'allocations'
144
+ else "measure#{measure_mode}"
145
+ end
146
+ end
147
+ end
148
+ end
data/lib/unprof.rb ADDED
@@ -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