ruby-prof 1.1.0
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.
- checksums.yaml +7 -0
- data/CHANGES +532 -0
- data/LICENSE +25 -0
- data/README.rdoc +5 -0
- data/Rakefile +110 -0
- data/bin/ruby-prof +380 -0
- data/bin/ruby-prof-check-trace +45 -0
- data/ext/ruby_prof/extconf.rb +36 -0
- data/ext/ruby_prof/rp_allocation.c +279 -0
- data/ext/ruby_prof/rp_allocation.h +31 -0
- data/ext/ruby_prof/rp_call_info.c +271 -0
- data/ext/ruby_prof/rp_call_info.h +35 -0
- data/ext/ruby_prof/rp_measure_allocations.c +52 -0
- data/ext/ruby_prof/rp_measure_memory.c +42 -0
- data/ext/ruby_prof/rp_measure_process_time.c +67 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +62 -0
- data/ext/ruby_prof/rp_measurement.c +230 -0
- data/ext/ruby_prof/rp_measurement.h +50 -0
- data/ext/ruby_prof/rp_method.c +630 -0
- data/ext/ruby_prof/rp_method.h +70 -0
- data/ext/ruby_prof/rp_profile.c +895 -0
- data/ext/ruby_prof/rp_profile.h +37 -0
- data/ext/ruby_prof/rp_stack.c +196 -0
- data/ext/ruby_prof/rp_stack.h +56 -0
- data/ext/ruby_prof/rp_thread.c +337 -0
- data/ext/ruby_prof/rp_thread.h +36 -0
- data/ext/ruby_prof/ruby_prof.c +48 -0
- data/ext/ruby_prof/ruby_prof.h +17 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +143 -0
- data/lib/ruby-prof.rb +52 -0
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +713 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
- data/lib/ruby-prof/call_info.rb +57 -0
- data/lib/ruby-prof/call_info_visitor.rb +38 -0
- data/lib/ruby-prof/compatibility.rb +109 -0
- data/lib/ruby-prof/exclude_common_methods.rb +198 -0
- data/lib/ruby-prof/measurement.rb +14 -0
- data/lib/ruby-prof/method_info.rb +90 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +127 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +51 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +182 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +151 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/flat_printer.rb +52 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
- data/lib/ruby-prof/printers/graph_printer.rb +114 -0
- data/lib/ruby-prof/printers/multi_printer.rb +127 -0
- data/lib/ruby-prof/profile.rb +33 -0
- data/lib/ruby-prof/rack.rb +171 -0
- data/lib/ruby-prof/task.rb +147 -0
- data/lib/ruby-prof/thread.rb +35 -0
- data/lib/ruby-prof/version.rb +3 -0
- data/lib/unprof.rb +10 -0
- data/ruby-prof.gemspec +58 -0
- data/test/abstract_printer_test.rb +26 -0
- data/test/alias_test.rb +129 -0
- data/test/basic_test.rb +129 -0
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/dynamic_method_test.rb +53 -0
- data/test/enumerable_test.rb +21 -0
- data/test/exceptions_test.rb +24 -0
- data/test/exclude_methods_test.rb +146 -0
- data/test/exclude_threads_test.rb +53 -0
- data/test/fiber_test.rb +73 -0
- data/test/gc_test.rb +96 -0
- data/test/line_number_test.rb +161 -0
- data/test/marshal_test.rb +119 -0
- data/test/measure_allocations.rb +30 -0
- data/test/measure_allocations_test.rb +385 -0
- data/test/measure_allocations_trace_test.rb +385 -0
- data/test/measure_memory_trace_test.rb +756 -0
- data/test/measure_process_time_test.rb +849 -0
- data/test/measure_times.rb +54 -0
- data/test/measure_wall_time_test.rb +459 -0
- data/test/multi_printer_test.rb +71 -0
- data/test/no_method_class_test.rb +15 -0
- data/test/parser_timings.rb +24 -0
- data/test/pause_resume_test.rb +166 -0
- data/test/prime.rb +56 -0
- data/test/printer_call_stack_test.rb +28 -0
- data/test/printer_call_tree_test.rb +31 -0
- data/test/printer_flat_test.rb +68 -0
- data/test/printer_graph_html_test.rb +60 -0
- data/test/printer_graph_test.rb +41 -0
- data/test/printers_test.rb +141 -0
- data/test/printing_recursive_graph_test.rb +81 -0
- data/test/rack_test.rb +157 -0
- data/test/recursive_test.rb +210 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +64 -0
- data/test/start_stop_test.rb +109 -0
- data/test/test_helper.rb +24 -0
- data/test/thread_test.rb +144 -0
- data/test/unique_call_path_test.rb +190 -0
- data/test/yarv_test.rb +56 -0
- metadata +191 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
require 'rake'
|
|
5
|
+
require 'rake/testtask'
|
|
6
|
+
require 'fileutils'
|
|
7
|
+
|
|
8
|
+
module RubyProf
|
|
9
|
+
|
|
10
|
+
# Define a task library for profiling unit tests with ruby-prof.
|
|
11
|
+
#
|
|
12
|
+
# All of the options provided by
|
|
13
|
+
# the Rake:TestTask are supported except the loader
|
|
14
|
+
# which is set to ruby-prof. For detailed information
|
|
15
|
+
# please refer to the Rake:TestTask documentation.
|
|
16
|
+
#
|
|
17
|
+
# ruby-prof specific options include:
|
|
18
|
+
#
|
|
19
|
+
# output_dir - For each file specified an output
|
|
20
|
+
# file with profile information will be
|
|
21
|
+
# written to the output directory.
|
|
22
|
+
# By default, the output directory is
|
|
23
|
+
# called "profile" and is created underneath
|
|
24
|
+
# the current working directory.
|
|
25
|
+
#
|
|
26
|
+
# printer - Specifies the output printer. Valid values include
|
|
27
|
+
# :flat, :graph, :graph_html and :call_tree.
|
|
28
|
+
#
|
|
29
|
+
# min_percent - Methods that take less than the specified percent
|
|
30
|
+
# will not be written out.
|
|
31
|
+
#
|
|
32
|
+
# Example:
|
|
33
|
+
#
|
|
34
|
+
# require 'ruby-prof/task'
|
|
35
|
+
#
|
|
36
|
+
# RubyProf::ProfileTask.new do |t|
|
|
37
|
+
# t.test_files = FileList['test/test*.rb']
|
|
38
|
+
# t.output_dir = "c:/temp"
|
|
39
|
+
# t.printer = :graph
|
|
40
|
+
# t.min_percent = 10
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
# If rake is invoked with a "TEST=filename" command line option,
|
|
44
|
+
# then the list of test files will be overridden to include only the
|
|
45
|
+
# filename specified on the command line. This provides an easy way
|
|
46
|
+
# to run just one test.
|
|
47
|
+
#
|
|
48
|
+
# If rake is invoked with a "TESTOPTS=options" command line option,
|
|
49
|
+
# then the given options are passed to the test process after a
|
|
50
|
+
# '--'. This allows Test::Unit options to be passed to the test
|
|
51
|
+
# suite.
|
|
52
|
+
#
|
|
53
|
+
# Examples:
|
|
54
|
+
#
|
|
55
|
+
# rake profile # run tests normally
|
|
56
|
+
# rake profile TEST=just_one_file.rb # run just one test file.
|
|
57
|
+
# rake profile TESTOPTS="-v" # run in verbose mode
|
|
58
|
+
# rake profile TESTOPTS="--runner=fox" # use the fox test runner
|
|
59
|
+
|
|
60
|
+
class ProfileTask < Rake::TestTask
|
|
61
|
+
attr_accessor :output_dir
|
|
62
|
+
attr_accessor :min_percent
|
|
63
|
+
attr_accessor :printer
|
|
64
|
+
|
|
65
|
+
def initialize(name = :profile)
|
|
66
|
+
super(name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Create the tasks defined by this task lib.
|
|
70
|
+
def define
|
|
71
|
+
lib_path = @libs.join(File::PATH_SEPARATOR)
|
|
72
|
+
desc "Profile" + (@name==:profile ? "" : " for #{@name}")
|
|
73
|
+
|
|
74
|
+
task @name do
|
|
75
|
+
create_output_directory
|
|
76
|
+
|
|
77
|
+
@ruby_opts.unshift( "-I#{lib_path}" )
|
|
78
|
+
@ruby_opts.unshift( "-w" ) if @warning
|
|
79
|
+
@ruby_opts.push("-S ruby-prof")
|
|
80
|
+
@ruby_opts.push("--printer #{@printer}")
|
|
81
|
+
@ruby_opts.push("--min_percent #{@min_percent}")
|
|
82
|
+
|
|
83
|
+
file_list.each do |file_path|
|
|
84
|
+
run_script(file_path)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Run script
|
|
91
|
+
def run_script(script_path)
|
|
92
|
+
run_code = ''
|
|
93
|
+
RakeFileUtils.verbose(@verbose) do
|
|
94
|
+
file_name = File.basename(script_path, File.extname(script_path))
|
|
95
|
+
case @printer
|
|
96
|
+
when :flat, :graph, :call_tree
|
|
97
|
+
file_name += ".txt"
|
|
98
|
+
when :graph_html
|
|
99
|
+
file_name += ".html"
|
|
100
|
+
else
|
|
101
|
+
file_name += ".txt"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
output_file_path = File.join(output_directory, file_name)
|
|
105
|
+
|
|
106
|
+
command_line = @ruby_opts.join(" ") +
|
|
107
|
+
" --file=" + output_file_path +
|
|
108
|
+
" " + script_path
|
|
109
|
+
|
|
110
|
+
puts "ruby " + command_line
|
|
111
|
+
# We have to catch the exeption to continue on. However,
|
|
112
|
+
# the error message will have been output to STDERR
|
|
113
|
+
# already by the time we get here so we don't have to
|
|
114
|
+
# do that again
|
|
115
|
+
begin
|
|
116
|
+
ruby command_line
|
|
117
|
+
rescue => e
|
|
118
|
+
STDOUT << e << "\n"
|
|
119
|
+
STDOUT.flush
|
|
120
|
+
end
|
|
121
|
+
puts ""
|
|
122
|
+
puts ""
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def output_directory
|
|
127
|
+
File.expand_path(@output_dir)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def create_output_directory
|
|
131
|
+
if not File.exist?(output_directory)
|
|
132
|
+
Dir.mkdir(output_directory)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def clean_output_directory
|
|
137
|
+
if File.exist?(output_directory)
|
|
138
|
+
files = Dir.glob(output_directory + '/*')
|
|
139
|
+
FileUtils.rm(files)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def option_list # :nodoc:
|
|
144
|
+
ENV['OPTIONS'] || @options.join(" ") || ""
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module RubyProf
|
|
2
|
+
class Thread
|
|
3
|
+
# Returns the root methods (ie, methods that were not called by other methods) that were profiled while
|
|
4
|
+
# this thread was executing. Generally there is only one root method (multiple root methods can occur
|
|
5
|
+
# when Profile#pause is used). By starting with the root methods, you can descend down the profile
|
|
6
|
+
# call tree.
|
|
7
|
+
def root_methods
|
|
8
|
+
self.methods.select do |method_info|
|
|
9
|
+
method_info.root?
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns the total time this thread was executed.
|
|
14
|
+
def total_time
|
|
15
|
+
self.root_methods.inject(0) do |sum, method_info|
|
|
16
|
+
method_info.callers.each do |call_info|
|
|
17
|
+
sum += call_info.total_time
|
|
18
|
+
end
|
|
19
|
+
sum
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns the amount of time this thread waited while other thread executed.
|
|
24
|
+
def wait_time
|
|
25
|
+
# wait_time, like self:time, is always method local
|
|
26
|
+
# thus we need to sum over all methods and call infos
|
|
27
|
+
self.methods.inject(0) do |sum, method_info|
|
|
28
|
+
method_info.callers.each do |call_info|
|
|
29
|
+
sum += call_info.wait_time
|
|
30
|
+
end
|
|
31
|
+
sum
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/unprof.rb
ADDED
data/ruby-prof.gemspec
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
4
|
+
require "ruby-prof/version"
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "ruby-prof"
|
|
8
|
+
|
|
9
|
+
spec.homepage = "https://github.com/ruby-prof/ruby-prof/"
|
|
10
|
+
spec.summary = "Fast Ruby profiler"
|
|
11
|
+
spec.description = <<-EOF
|
|
12
|
+
ruby-prof is a fast code profiler for Ruby. It is a C extension and
|
|
13
|
+
therefore is many times faster than the standard Ruby profiler. It
|
|
14
|
+
supports both flat and graph profiles. For each method, graph profiles
|
|
15
|
+
show how long the method ran, which methods called it and which
|
|
16
|
+
methods it called. RubyProf generate both text and html and can output
|
|
17
|
+
it to standard out or to a file.
|
|
18
|
+
EOF
|
|
19
|
+
spec.license = 'BSD-2-Clause'
|
|
20
|
+
spec.version = RubyProf::VERSION
|
|
21
|
+
|
|
22
|
+
spec.author = "Shugo Maeda, Charlie Savage, Roger Pack, Stefan Kaes"
|
|
23
|
+
spec.email = "shugo@ruby-lang.org, cfis@savagexi.com, rogerdpack@gmail.com, skaes@railsexpress.de"
|
|
24
|
+
spec.platform = Gem::Platform::RUBY
|
|
25
|
+
spec.require_path = "lib"
|
|
26
|
+
spec.bindir = "bin"
|
|
27
|
+
spec.executables = ["ruby-prof", "ruby-prof-check-trace"]
|
|
28
|
+
spec.extensions = ["ext/ruby_prof/extconf.rb"]
|
|
29
|
+
spec.files = Dir['CHANGES',
|
|
30
|
+
'LICENSE',
|
|
31
|
+
'Rakefile',
|
|
32
|
+
'README.rdoc',
|
|
33
|
+
'ruby-prof.gemspec',
|
|
34
|
+
'bin/ruby-prof',
|
|
35
|
+
'bin/ruby-prof-check-trace',
|
|
36
|
+
'doc/**/*',
|
|
37
|
+
'examples/*',
|
|
38
|
+
'ext/ruby_prof/extconf.rb',
|
|
39
|
+
'ext/ruby_prof/*.c',
|
|
40
|
+
'ext/ruby_prof/*.h',
|
|
41
|
+
'ext/ruby_prof/vc/*.sln',
|
|
42
|
+
'ext/ruby_prof/vc/*.vcxproj',
|
|
43
|
+
'lib/ruby-prof.rb',
|
|
44
|
+
'lib/unprof.rb',
|
|
45
|
+
'lib/ruby-prof/*.rb',
|
|
46
|
+
'lib/ruby-prof/assets/*',
|
|
47
|
+
'lib/ruby-prof/profile/*.rb',
|
|
48
|
+
'lib/ruby-prof/printers/*.rb',
|
|
49
|
+
'test/*.rb']
|
|
50
|
+
|
|
51
|
+
spec.test_files = Dir["test/test_*.rb"]
|
|
52
|
+
spec.required_ruby_version = '>= 2.4.0'
|
|
53
|
+
spec.date = Time.now.strftime('%Y-%m-%d')
|
|
54
|
+
spec.homepage = 'https://github.com/ruby-prof/ruby-prof'
|
|
55
|
+
spec.add_development_dependency('minitest')
|
|
56
|
+
spec.add_development_dependency('rake-compiler')
|
|
57
|
+
spec.add_development_dependency('rdoc')
|
|
58
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
|
5
|
+
|
|
6
|
+
class AbstractPrinterTest < TestCase
|
|
7
|
+
def setup
|
|
8
|
+
@result = {}
|
|
9
|
+
@printer = RubyProf::AbstractPrinter.new(@result)
|
|
10
|
+
@options = {}
|
|
11
|
+
@printer.setup_options(@options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def with_const_stubbed(name, value)
|
|
17
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
|
18
|
+
old_value = Object.const_get(name)
|
|
19
|
+
|
|
20
|
+
Object.const_set(name, value)
|
|
21
|
+
yield
|
|
22
|
+
Object.const_set(name, old_value)
|
|
23
|
+
|
|
24
|
+
$VERBOSE = old_verbose
|
|
25
|
+
end
|
|
26
|
+
end
|
data/test/alias_test.rb
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
5
|
+
|
|
6
|
+
class AliasTest < TestCase
|
|
7
|
+
class TestMe
|
|
8
|
+
def some_method
|
|
9
|
+
sleep(0.1)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
alias :some_method_original :some_method
|
|
13
|
+
def some_method
|
|
14
|
+
some_method_original
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def setup
|
|
19
|
+
# Need to use wall time for this test due to the sleep calls
|
|
20
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# This test only correct works on Ruby 2.5 and higher because - see:
|
|
24
|
+
# https://bugs.ruby-lang.org/issues/12747
|
|
25
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
|
|
26
|
+
def test_alias
|
|
27
|
+
result = RubyProf.profile do
|
|
28
|
+
TestMe.new.some_method
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
methods = result.threads.first.methods
|
|
32
|
+
assert_equal(6, methods.count)
|
|
33
|
+
|
|
34
|
+
# Method 0
|
|
35
|
+
method = methods[0]
|
|
36
|
+
assert_equal('AliasTest#test_alias', method.full_name)
|
|
37
|
+
assert_equal(28, method.line)
|
|
38
|
+
refute(method.recursive?)
|
|
39
|
+
|
|
40
|
+
assert_equal(1, method.callers.count)
|
|
41
|
+
call_info = method.callers[0]
|
|
42
|
+
assert_nil(call_info.parent)
|
|
43
|
+
assert_equal(28, call_info.line)
|
|
44
|
+
|
|
45
|
+
assert_equal(2, method.callees.count)
|
|
46
|
+
call_info = method.callees[0]
|
|
47
|
+
assert_equal('Class#new', call_info.target.full_name)
|
|
48
|
+
assert_equal(28, call_info.line)
|
|
49
|
+
|
|
50
|
+
call_info = method.callees[1]
|
|
51
|
+
assert_equal('AliasTest::TestMe#some_method', call_info.target.full_name)
|
|
52
|
+
assert_equal(28, call_info.line)
|
|
53
|
+
|
|
54
|
+
# Method 1
|
|
55
|
+
method = methods[1]
|
|
56
|
+
assert_equal('Class#new', method.full_name)
|
|
57
|
+
assert_equal(0, method.line)
|
|
58
|
+
refute(method.recursive?)
|
|
59
|
+
|
|
60
|
+
assert_equal(1, method.callers.count)
|
|
61
|
+
call_info = method.callers[0]
|
|
62
|
+
assert_equal('AliasTest#test_alias', call_info.parent.full_name)
|
|
63
|
+
assert_equal(28, call_info.line)
|
|
64
|
+
|
|
65
|
+
assert_equal(1, method.callees.count)
|
|
66
|
+
call_info = method.callees[0]
|
|
67
|
+
assert_equal('BasicObject#initialize', call_info.target.full_name)
|
|
68
|
+
assert_equal(0, call_info.line)
|
|
69
|
+
|
|
70
|
+
# Method 2
|
|
71
|
+
method = methods[2]
|
|
72
|
+
assert_equal('BasicObject#initialize', method.full_name)
|
|
73
|
+
assert_equal(0, method.line)
|
|
74
|
+
refute(method.recursive?)
|
|
75
|
+
|
|
76
|
+
assert_equal(1, method.callers.count)
|
|
77
|
+
call_info = method.callers[0]
|
|
78
|
+
assert_equal('Class#new', call_info.parent.full_name)
|
|
79
|
+
assert_equal(0, call_info.line)
|
|
80
|
+
|
|
81
|
+
assert_equal(0, method.callees.count)
|
|
82
|
+
|
|
83
|
+
# Method 3
|
|
84
|
+
method = methods[3]
|
|
85
|
+
assert_equal('AliasTest::TestMe#some_method', method.full_name)
|
|
86
|
+
assert_equal(13, method.line)
|
|
87
|
+
refute(method.recursive?)
|
|
88
|
+
|
|
89
|
+
assert_equal(1, method.callers.count)
|
|
90
|
+
call_info = method.callers[0]
|
|
91
|
+
assert_equal('AliasTest#test_alias', call_info.parent.full_name)
|
|
92
|
+
assert_equal(28, call_info.line)
|
|
93
|
+
|
|
94
|
+
assert_equal(1, method.callees.count)
|
|
95
|
+
call_info = method.callees[0]
|
|
96
|
+
assert_equal('AliasTest::TestMe#some_method_original', call_info.target.full_name)
|
|
97
|
+
assert_equal(14, call_info.line)
|
|
98
|
+
|
|
99
|
+
# Method 4
|
|
100
|
+
method = methods[4]
|
|
101
|
+
assert_equal('AliasTest::TestMe#some_method_original', method.full_name)
|
|
102
|
+
assert_equal(8, method.line)
|
|
103
|
+
refute(method.recursive?)
|
|
104
|
+
|
|
105
|
+
assert_equal(1, method.callers.count)
|
|
106
|
+
call_info = method.callers[0]
|
|
107
|
+
assert_equal('AliasTest::TestMe#some_method', call_info.parent.full_name)
|
|
108
|
+
assert_equal(14, call_info.line)
|
|
109
|
+
|
|
110
|
+
assert_equal(1, method.callees.count)
|
|
111
|
+
call_info = method.callees[0]
|
|
112
|
+
assert_equal('Kernel#sleep', call_info.target.full_name)
|
|
113
|
+
assert_equal(9, call_info.line)
|
|
114
|
+
|
|
115
|
+
# Method 5
|
|
116
|
+
method = methods[5]
|
|
117
|
+
assert_equal('Kernel#sleep', method.full_name)
|
|
118
|
+
assert_equal(0, method.line)
|
|
119
|
+
refute(method.recursive?)
|
|
120
|
+
|
|
121
|
+
assert_equal(1, method.callers.count)
|
|
122
|
+
call_info = method.callers[0]
|
|
123
|
+
assert_equal('AliasTest::TestMe#some_method_original', call_info.parent.full_name)
|
|
124
|
+
assert_equal(9, call_info.line)
|
|
125
|
+
|
|
126
|
+
assert_equal(0, method.callees.count)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
data/test/basic_test.rb
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
|
5
|
+
require_relative './measure_times'
|
|
6
|
+
|
|
7
|
+
class BasicTest < TestCase
|
|
8
|
+
def setup
|
|
9
|
+
# Need to use wall time for this test due to the sleep calls
|
|
10
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start
|
|
14
|
+
RubyProf.start
|
|
15
|
+
RubyProf::C1.sleep_wait
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_running
|
|
19
|
+
assert(!RubyProf.running?)
|
|
20
|
+
RubyProf.start
|
|
21
|
+
assert(RubyProf.running?)
|
|
22
|
+
RubyProf.stop
|
|
23
|
+
assert(!RubyProf.running?)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_double_profile
|
|
27
|
+
RubyProf.start
|
|
28
|
+
assert_raises(RuntimeError) do
|
|
29
|
+
RubyProf.start
|
|
30
|
+
end
|
|
31
|
+
RubyProf.stop
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_no_block
|
|
35
|
+
assert_raises(ArgumentError) do
|
|
36
|
+
RubyProf.profile
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_traceback
|
|
41
|
+
RubyProf.start
|
|
42
|
+
assert_raises(NoMethodError) do
|
|
43
|
+
RubyProf.xxx
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
RubyProf.stop
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_leave_method
|
|
50
|
+
start
|
|
51
|
+
sleep 0.15
|
|
52
|
+
profile = RubyProf.stop
|
|
53
|
+
|
|
54
|
+
assert_equal(1, profile.threads.count)
|
|
55
|
+
|
|
56
|
+
thread = profile.threads.first
|
|
57
|
+
assert_in_delta(0.25, thread.total_time, 0.05)
|
|
58
|
+
|
|
59
|
+
root_methods = thread.root_methods.sort
|
|
60
|
+
assert_equal(2, root_methods.count)
|
|
61
|
+
assert_equal("BasicTest#start", root_methods[0].full_name)
|
|
62
|
+
assert_equal("BasicTest#test_leave_method", root_methods[1].full_name)
|
|
63
|
+
|
|
64
|
+
assert_equal(4, thread.methods.length)
|
|
65
|
+
methods = profile.threads.first.methods.sort
|
|
66
|
+
|
|
67
|
+
# Check times
|
|
68
|
+
assert_equal("<Class::RubyProf::C1>#sleep_wait", methods[0].full_name)
|
|
69
|
+
assert_in_delta(0.1, methods[0].total_time, 0.05)
|
|
70
|
+
assert_in_delta(0.0, methods[0].wait_time, 0.05)
|
|
71
|
+
assert_in_delta(0.0, methods[0].self_time, 0.05)
|
|
72
|
+
|
|
73
|
+
assert_equal("BasicTest#start", methods[1].full_name)
|
|
74
|
+
assert_in_delta(0.1, methods[1].total_time, 0.05)
|
|
75
|
+
assert_in_delta(0.0, methods[1].wait_time, 0.05)
|
|
76
|
+
assert_in_delta(0.0, methods[1].self_time, 0.05)
|
|
77
|
+
|
|
78
|
+
assert_equal("BasicTest#test_leave_method", methods[2].full_name)
|
|
79
|
+
assert_in_delta(0.15, methods[2].total_time, 0.05)
|
|
80
|
+
assert_in_delta(0.0, methods[2].wait_time, 0.05)
|
|
81
|
+
assert_in_delta(0.0, methods[2].self_time, 0.05)
|
|
82
|
+
|
|
83
|
+
assert_equal("Kernel#sleep", methods[3].full_name)
|
|
84
|
+
assert_in_delta(0.25, methods[3].total_time, 0.05)
|
|
85
|
+
assert_in_delta(0.0, methods[3].wait_time, 0.05)
|
|
86
|
+
assert_in_delta(0.25, methods[3].self_time, 0.05)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_leave_method_2
|
|
90
|
+
start
|
|
91
|
+
RubyProf::C1.sleep_wait
|
|
92
|
+
RubyProf::C1.sleep_wait
|
|
93
|
+
profile = RubyProf.stop
|
|
94
|
+
|
|
95
|
+
assert_equal(1, profile.threads.count)
|
|
96
|
+
|
|
97
|
+
thread = profile.threads.first
|
|
98
|
+
assert_in_delta(0.3, thread.total_time, 0.05)
|
|
99
|
+
|
|
100
|
+
root_methods = thread.root_methods.sort
|
|
101
|
+
assert_equal(2, root_methods.count)
|
|
102
|
+
assert_equal("BasicTest#start", root_methods[0].full_name)
|
|
103
|
+
assert_equal("BasicTest#test_leave_method_2", root_methods[1].full_name)
|
|
104
|
+
|
|
105
|
+
assert_equal(4, thread.methods.length)
|
|
106
|
+
methods = profile.threads.first.methods.sort
|
|
107
|
+
|
|
108
|
+
# Check times
|
|
109
|
+
assert_equal("BasicTest#start", methods[0].full_name)
|
|
110
|
+
assert_in_delta(0.1, methods[0].total_time, 0.05)
|
|
111
|
+
assert_in_delta(0.0, methods[0].wait_time, 0.05)
|
|
112
|
+
assert_in_delta(0.0, methods[0].self_time, 0.05)
|
|
113
|
+
|
|
114
|
+
assert_equal("BasicTest#test_leave_method_2", methods[1].full_name)
|
|
115
|
+
assert_in_delta(0.2, methods[1].total_time, 0.05)
|
|
116
|
+
assert_in_delta(0.0, methods[1].wait_time, 0.05)
|
|
117
|
+
assert_in_delta(0.0, methods[1].self_time, 0.05)
|
|
118
|
+
|
|
119
|
+
assert_equal("Kernel#sleep", methods[2].full_name)
|
|
120
|
+
assert_in_delta(0.3, methods[2].total_time, 0.05)
|
|
121
|
+
assert_in_delta(0.0, methods[2].wait_time, 0.05)
|
|
122
|
+
assert_in_delta(0.3, methods[2].self_time, 0.05)
|
|
123
|
+
|
|
124
|
+
assert_equal("<Class::RubyProf::C1>#sleep_wait", methods[3].full_name)
|
|
125
|
+
assert_in_delta(0.3, methods[3].total_time, 0.05)
|
|
126
|
+
assert_in_delta(0.0, methods[3].wait_time, 0.05)
|
|
127
|
+
assert_in_delta(0.0, methods[3].self_time, 0.05)
|
|
128
|
+
end
|
|
129
|
+
end
|