ruby-prof 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGES +17 -0
  2. data/LICENSE +23 -0
  3. data/README +220 -0
  4. data/Rakefile +141 -0
  5. data/bin/ruby-prof +154 -0
  6. data/doc/classes/RubyProf.html +563 -0
  7. data/doc/classes/RubyProf/CallInfo.html +274 -0
  8. data/doc/classes/RubyProf/FlatPrinter.html +207 -0
  9. data/doc/classes/RubyProf/GraphHtmlPrinter.html +538 -0
  10. data/doc/classes/RubyProf/GraphPrinter.html +240 -0
  11. data/doc/classes/RubyProf/MethodInfo.html +556 -0
  12. data/doc/classes/RubyProf/ProfileTask.html +395 -0
  13. data/doc/classes/RubyProf/Result.html +234 -0
  14. data/doc/created.rid +1 -0
  15. data/doc/files/LICENSE.html +142 -0
  16. data/doc/files/README.html +376 -0
  17. data/doc/files/bin/ruby-prof.html +143 -0
  18. data/doc/files/examples/flat_txt.html +187 -0
  19. data/doc/files/examples/graph_html.html +948 -0
  20. data/doc/files/examples/graph_txt.html +305 -0
  21. data/doc/files/ext/ruby_prof_c.html +101 -0
  22. data/doc/files/lib/ruby-prof/flat_printer_rb.html +101 -0
  23. data/doc/files/lib/ruby-prof/graph_html_printer_rb.html +108 -0
  24. data/doc/files/lib/ruby-prof/graph_printer_rb.html +101 -0
  25. data/doc/files/lib/ruby-prof/profiletask_rb.html +109 -0
  26. data/doc/files/lib/ruby-prof_rb.html +111 -0
  27. data/doc/files/lib/unprof_rb.html +108 -0
  28. data/doc/fr_class_index.html +34 -0
  29. data/doc/fr_file_index.html +39 -0
  30. data/doc/fr_method_index.html +67 -0
  31. data/doc/index.html +24 -0
  32. data/doc/rdoc-style.css +208 -0
  33. data/examples/flat.txt +57 -0
  34. data/examples/graph.html +827 -0
  35. data/examples/graph.txt +171 -0
  36. data/ext/extconf.rb +19 -0
  37. data/ext/ruby_prof.c +1433 -0
  38. data/lib/ruby-prof.rb +38 -0
  39. data/lib/ruby-prof/flat_printer.rb +76 -0
  40. data/lib/ruby-prof/graph_html_printer.rb +227 -0
  41. data/lib/ruby-prof/graph_printer.rb +142 -0
  42. data/lib/ruby-prof/profiletask.rb +150 -0
  43. data/lib/unprof.rb +8 -0
  44. data/test/basic_test.rb +141 -0
  45. data/test/clock_mode_test.rb +73 -0
  46. data/test/module_test.rb +45 -0
  47. data/test/prime.rb +58 -0
  48. data/test/prime_test.rb +24 -0
  49. data/test/printers_test.rb +28 -0
  50. data/test/recursive_test.rb +55 -0
  51. data/test/test.rb +3 -0
  52. data/test/test_helper.rb +45 -0
  53. data/test/test_suite.rb +9 -0
  54. data/test/thread_test.rb +32 -0
  55. data/test/timing_test.rb +90 -0
  56. metadata +121 -0
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+
6
+ module RubyProf
7
+
8
+ # Create a profile task. All of the options provided by
9
+ # the Rake:TestTask are supported except the loader
10
+ # which is set to ruby-prof. For detailed information
11
+ # please refer to the Rake:TestTask documentation.
12
+ #
13
+ # ruby-prof specific options include:
14
+ #
15
+ # output_dir - For each file specified an output
16
+ # file with profile information will be
17
+ # written to the output directory.
18
+ # By default, the output directory is
19
+ # called "profile" and is created underneath
20
+ # the current working directory.
21
+ #
22
+ # printer - Specifies the output printer. Valid values include
23
+ # :flat, :graph, and :graph_html.
24
+ #
25
+ # min_percent - Methods that take less than the specified percent
26
+ # will not be written out.
27
+ #
28
+ # Example:
29
+ #
30
+ # require 'ruby-prof/task'
31
+ #
32
+ # ruby-prof::RubyProfTask.new do |t|
33
+ # t.test_files = FileList['test/test*.rb']
34
+ # t.output_dir = "c:/temp"
35
+ # t.printer = :graph
36
+ # t.min_percent = 10
37
+ # end
38
+ #
39
+ # If the task is invoked with a "test=filename" command line option,
40
+ # then the list of test files will be overridden to include only the
41
+ # filename specified on the command line. This provides an easy way
42
+ # to run just one test.
43
+ #
44
+ # If rake is invoked with a "options=options" command line option,
45
+ # then the given options are passed to ruby-prof.
46
+ #
47
+ # If rake is invoked with a "ruby-profPATH=path/to/ruby-prof" command line option,
48
+ # then the given ruby-prof executable will be used; otherwise the one in your
49
+ # PATH will be used.
50
+ #
51
+ # Examples:
52
+ #
53
+ # rake ruby-prof # profiles all unit tests
54
+ # rake ruby-prof TEST=just_one_file.rb # profiles one unit test
55
+ # rake ruby-prof PATTERN=*.rb # profiles all files
56
+
57
+ class ProfileTask < Rake::TestTask
58
+ attr_writer :output_dir
59
+ attr_writer :min_percent
60
+ attr_writer :printer
61
+
62
+ def initialize(name=:profile)
63
+ @name = name
64
+ @libs = ["lib"]
65
+ @pattern = nil
66
+ @options = Array.new
67
+ @test_files = nil
68
+ @verbose = false
69
+ @warning = false
70
+ @loader = :ruby_prof
71
+ @ruby_opts = []
72
+ @output_dir = File.join(Dir.getwd, "profile")
73
+ @printer = :graph
74
+ @min_percent = 0
75
+ yield self if block_given?
76
+ @pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil?
77
+ define
78
+ end
79
+
80
+ # Create the tasks defined by this task lib.
81
+ def define
82
+ create_output_directory
83
+
84
+ lib_path = @libs.join(File::PATH_SEPARATOR)
85
+ desc "Profile" + (@name==:profile ? "" : " for #{@name}")
86
+
87
+ task @name do
88
+ @ruby_opts.unshift( "-I#{lib_path}" )
89
+ @ruby_opts.unshift( "-w" ) if @warning
90
+ @ruby_opts.push("-S ruby-prof")
91
+ @ruby_opts.push("--printer #{@printer}")
92
+ @ruby_opts.push("--min_percent #{@min_percent}")
93
+
94
+ file_list.each do |file_path|
95
+ run_script(file_path)
96
+ end
97
+ end
98
+ self
99
+ end
100
+
101
+ # Run script
102
+ def run_script(script_path)
103
+ run_code = ''
104
+ RakeFileUtils.verbose(@verbose) do
105
+ file_name = File.basename(script_path, File.extname(script_path))
106
+ case @printer
107
+ when :flat, :graph
108
+ file_name += ".txt"
109
+ when :graph_html
110
+ file_name += ".html"
111
+ else
112
+ file_name += ".txt"
113
+ end
114
+
115
+ output_file_path = File.join(output_directory, file_name)
116
+
117
+ command_line = @ruby_opts.join(" ") +
118
+ " --file=" + output_file_path +
119
+ " " + script_path
120
+
121
+ puts "ruby " + command_line
122
+ # We have to catch the exeption to continue on. However,
123
+ # the error message will have been output to STDERR
124
+ # already by the time we get here so we don't have to
125
+ # do that again
126
+ begin
127
+ ruby command_line
128
+ rescue
129
+ end
130
+ puts ""
131
+ puts ""
132
+ end
133
+ end
134
+
135
+ def output_directory
136
+ File.expand_path(@output_dir)
137
+ end
138
+
139
+ def create_output_directory
140
+ if not File.exist?(output_directory)
141
+ Dir.mkdir(output_directory)
142
+ end
143
+ end
144
+
145
+ def option_list # :nodoc:
146
+ ENV['TESTOPTS'] || @options.join(" ") || ""
147
+ end
148
+ end
149
+ end
150
+
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,141 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+
7
+ class C1
8
+ def C1.hello
9
+ end
10
+
11
+ def hello
12
+ end
13
+ end
14
+
15
+ module M1
16
+ def hello
17
+ end
18
+ end
19
+
20
+ class C2
21
+ include M1
22
+ extend M1
23
+ end
24
+
25
+ class C3
26
+ def hello
27
+ end
28
+ end
29
+
30
+ module M4
31
+ def hello
32
+ end
33
+ end
34
+
35
+ module M5
36
+ include M4
37
+ def goodbye
38
+ hello
39
+ end
40
+ end
41
+
42
+ class C6
43
+ include M5
44
+ def test
45
+ goodbye
46
+ end
47
+ end
48
+
49
+ class BasicTest < Test::Unit::TestCase
50
+ def test_double_profile
51
+ RubyProf.start
52
+ assert_raise(RuntimeError) do
53
+ RubyProf.start
54
+ end
55
+
56
+ assert_raise(RuntimeError) do
57
+ RubyProf.profile do
58
+ puts 1
59
+ end
60
+ end
61
+ RubyProf.stop
62
+ end
63
+
64
+
65
+ def test_no_block
66
+ assert_raise(ArgumentError) do
67
+ RubyProf.profile
68
+ end
69
+ end
70
+
71
+ def test_class_and_instance_methods
72
+ result = RubyProf.profile do
73
+ C1.hello
74
+ C1.new.hello
75
+ end
76
+
77
+ methods = result.threads.values.first
78
+
79
+ # Length should be 6:
80
+ # 1 top level,
81
+ # 1 Class.new
82
+ # 1 Class:Object allocate
83
+ # 1 for Object.initialize
84
+ # 1 for Class hello
85
+ # 1 for Object hello
86
+ assert_equal(6, methods.length)
87
+
88
+ # Check class method
89
+ method1 = methods['<Class::C1>#hello']
90
+ assert_not_nil(method1)
91
+
92
+ # Check instance method
93
+ method1 = methods['C1#hello']
94
+ assert_not_nil(method1)
95
+ end
96
+
97
+ def test_module_methods
98
+ result = RubyProf.profile do
99
+ C2.hello
100
+ C2.new.hello
101
+ end
102
+
103
+ methods = result.threads.values.first
104
+
105
+ # Length should be 5:
106
+ # 1 top level,
107
+ # 1 Class.new
108
+ # 1 Class:Object allocate
109
+ # 1 for Object.initialize
110
+ # 1 for hello
111
+ assert_equal(5, methods.length)
112
+
113
+ # Check class method
114
+ method1 = methods['M1#hello']
115
+ assert_not_nil(method1)
116
+ assert_equal(2, method1.called)
117
+ end
118
+
119
+ def test_singleton
120
+ c3 = C3.new
121
+
122
+ class << c3
123
+ def hello
124
+ end
125
+ end
126
+
127
+ result = RubyProf.profile do
128
+ c3.hello
129
+ end
130
+
131
+ methods = result.threads.values.first
132
+
133
+ # Length should be 2 - one for top level
134
+ # and one for the singleton method.
135
+ assert_equal(2, methods.length)
136
+
137
+ # Check singleton method
138
+ method1 = methods['<Object::C3>#hello']
139
+ assert_not_nil(method1)
140
+ end
141
+ end
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+ require 'prime'
7
+
8
+
9
+ # -- Tests ----
10
+ class ClockModeTest < Test::Unit::TestCase
11
+ def test_clock
12
+ return
13
+ RubyProf::clock_mode = RubyProf::PROCESS_TIME
14
+ assert_equal(RubyProf::PROCESS_TIME, RubyProf::clock_mode)
15
+ result = RubyProf.profile do
16
+ run_primes
17
+ end
18
+
19
+ print_results(result)
20
+
21
+ result.threads.values.each do |methods|
22
+ methods.values.each do |method|
23
+ check_parent_times(method)
24
+ check_parent_calls(method)
25
+ check_child_times(method)
26
+ end
27
+ end
28
+ end
29
+
30
+ def test_gettimeofday
31
+ return
32
+ RubyProf::clock_mode = RubyProf::WALL_TIME
33
+ assert_equal(RubyProf::WALL_TIME, RubyProf::clock_mode)
34
+ result = RubyProf.profile do
35
+ run_primes
36
+ end
37
+
38
+ print_results(result)
39
+
40
+ result.threads.values.each do |methods|
41
+ methods.values.each do |method|
42
+ check_parent_times(method)
43
+ check_parent_calls(method)
44
+ check_child_times(method)
45
+ end
46
+ end
47
+ end
48
+
49
+ def test_cpu
50
+ #return
51
+ RubyProf::clock_mode = RubyProf::CPU_TIME
52
+ assert_equal(RubyProf::CPU, RubyProf::clock_mode)
53
+ result = RubyProf.profile do
54
+ run_primes
55
+ end
56
+
57
+ print_results(result)
58
+
59
+ result.threads.values.each do |methods|
60
+ methods.values.each do |method|
61
+ check_parent_times(method)
62
+ check_parent_calls(method)
63
+ check_child_times(method)
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_invalid
69
+ assert_raise(ArgumentError) do
70
+ RubyProf::clock_mode = 7777
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+
7
+
8
+ module Foo
9
+ def Foo::hello
10
+ end
11
+ end
12
+
13
+ module Bar
14
+ def Bar::hello
15
+ Foo::hello
16
+ end
17
+
18
+ def hello
19
+ Bar::hello
20
+ end
21
+ end
22
+
23
+ include Bar
24
+
25
+ class BasicTest < Test::Unit::TestCase
26
+ def test_nested_modules
27
+ result = RubyProf.profile do
28
+ hello
29
+ end
30
+
31
+ methods = result.threads.values.first
32
+
33
+ # Length should be 4s
34
+ assert_equal(4, methods.length)
35
+
36
+ method1 = methods['Bar#hello']
37
+ assert_not_nil(method1)
38
+
39
+ method1 = methods['<Module::Bar>#hello']
40
+ assert_not_nil(method1)
41
+
42
+ method1 = methods['<Module::Foo>#hello']
43
+ assert_not_nil(method1)
44
+ end
45
+ end
data/test/prime.rb ADDED
@@ -0,0 +1,58 @@
1
+ # A silly little test program that finds prime numbers. It
2
+ # is intentionally badly designed to show off the use
3
+ # or ruby-prof.
4
+ #
5
+ # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
+
7
+ def make_random_array(length, maxnum)
8
+ result = Array.new(length)
9
+ result.each_index do |i|
10
+ result[i] = rand(maxnum)
11
+ end
12
+
13
+ result
14
+ end
15
+
16
+ def is_prime(x)
17
+ y = 2
18
+ y.upto(x-1) do |i|
19
+ return false if (x % i) == 0
20
+ end
21
+ true
22
+ end
23
+
24
+ def find_primes(arr)
25
+ result = arr.select do |value|
26
+ is_prime(value)
27
+ end
28
+ result
29
+ end
30
+
31
+ def find_largest(primes)
32
+ largest = primes.first
33
+
34
+ # Intentionally use upto for example purposes
35
+ # (upto is also called from is_prime)
36
+ 0.upto(primes.length-1) do |i|
37
+ sleep(0.02)
38
+ prime = primes[i]
39
+ if prime > largest
40
+ largest = prime
41
+ end
42
+ end
43
+ largest
44
+ end
45
+
46
+ def run_primes
47
+ length = 500
48
+ maxnum = 10000
49
+
50
+ # Create random numbers
51
+ random_array = make_random_array(length, maxnum)
52
+
53
+ # Find the primes
54
+ primes = find_primes(random_array)
55
+
56
+ # Find the largest primes
57
+ largest = find_largest(primes)
58
+ end