ruby-prof 0.4.0-mswin32
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 +17 -0
- data/LICENSE +23 -0
- data/README +220 -0
- data/Rakefile +141 -0
- data/bin/ruby-prof +154 -0
- data/doc/classes/RubyProf.html +563 -0
- data/doc/classes/RubyProf/CallInfo.html +274 -0
- data/doc/classes/RubyProf/FlatPrinter.html +207 -0
- data/doc/classes/RubyProf/GraphHtmlPrinter.html +538 -0
- data/doc/classes/RubyProf/GraphPrinter.html +240 -0
- data/doc/classes/RubyProf/MethodInfo.html +556 -0
- data/doc/classes/RubyProf/ProfileTask.html +395 -0
- data/doc/classes/RubyProf/Result.html +234 -0
- data/doc/created.rid +1 -0
- data/doc/files/LICENSE.html +142 -0
- data/doc/files/README.html +376 -0
- data/doc/files/bin/ruby-prof.html +143 -0
- data/doc/files/examples/flat_txt.html +187 -0
- data/doc/files/examples/graph_html.html +948 -0
- data/doc/files/examples/graph_txt.html +305 -0
- data/doc/files/ext/ruby_prof_c.html +101 -0
- data/doc/files/lib/ruby-prof/flat_printer_rb.html +101 -0
- data/doc/files/lib/ruby-prof/graph_html_printer_rb.html +108 -0
- data/doc/files/lib/ruby-prof/graph_printer_rb.html +101 -0
- data/doc/files/lib/ruby-prof/profiletask_rb.html +109 -0
- data/doc/files/lib/ruby-prof_rb.html +111 -0
- data/doc/files/lib/unprof_rb.html +108 -0
- data/doc/fr_class_index.html +34 -0
- data/doc/fr_file_index.html +39 -0
- data/doc/fr_method_index.html +67 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/examples/flat.txt +57 -0
- data/examples/graph.html +827 -0
- data/examples/graph.txt +171 -0
- data/ext/extconf.rb +19 -0
- data/ext/ruby_prof.c +1433 -0
- data/lib/ruby-prof.rb +38 -0
- data/lib/ruby-prof/flat_printer.rb +76 -0
- data/lib/ruby-prof/graph_html_printer.rb +227 -0
- data/lib/ruby-prof/graph_printer.rb +142 -0
- data/lib/ruby-prof/profiletask.rb +150 -0
- data/lib/ruby_prof.so +0 -0
- data/lib/unprof.rb +8 -0
- data/test/basic_test.rb +141 -0
- data/test/clock_mode_test.rb +73 -0
- data/test/module_test.rb +45 -0
- data/test/prime.rb +58 -0
- data/test/prime_test.rb +24 -0
- data/test/printers_test.rb +28 -0
- data/test/recursive_test.rb +55 -0
- data/test/test.rb +3 -0
- data/test/test_helper.rb +45 -0
- data/test/test_suite.rb +9 -0
- data/test/thread_test.rb +32 -0
- data/test/timing_test.rb +90 -0
- metadata +122 -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/ruby_prof.so
ADDED
Binary file
|
data/lib/unprof.rb
ADDED
data/test/basic_test.rb
ADDED
@@ -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
|
data/test/module_test.rb
ADDED
@@ -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
|