airbnb-ruby-prof 0.0.1
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 +483 -0
- data/LICENSE +25 -0
- data/README.rdoc +426 -0
- data/Rakefile +51 -0
- data/bin/ruby-prof +279 -0
- data/bin/ruby-prof-check-trace +45 -0
- data/examples/flat.txt +50 -0
- data/examples/graph.dot +84 -0
- data/examples/graph.html +823 -0
- data/examples/graph.txt +139 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +760 -0
- data/examples/multi.grind.dat +114 -0
- data/examples/multi.stack.html +547 -0
- data/examples/stack.html +547 -0
- data/ext/ruby_prof/extconf.rb +67 -0
- data/ext/ruby_prof/rp_call_info.c +374 -0
- data/ext/ruby_prof/rp_call_info.h +59 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
- data/ext/ruby_prof/rp_measure.c +71 -0
- data/ext/ruby_prof/rp_measure.h +56 -0
- data/ext/ruby_prof/rp_measure_allocations.c +74 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
- data/ext/ruby_prof/rp_measure_memory.c +75 -0
- data/ext/ruby_prof/rp_measure_process_time.c +69 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
- data/ext/ruby_prof/rp_method.c +717 -0
- data/ext/ruby_prof/rp_method.h +79 -0
- data/ext/ruby_prof/rp_stack.c +221 -0
- data/ext/ruby_prof/rp_stack.h +81 -0
- data/ext/ruby_prof/rp_thread.c +312 -0
- data/ext/ruby_prof/rp_thread.h +36 -0
- data/ext/ruby_prof/ruby_prof.c +800 -0
- data/ext/ruby_prof/ruby_prof.h +64 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
- data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
- data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
- data/lib/ruby-prof.rb +63 -0
- data/lib/ruby-prof/aggregate_call_info.rb +76 -0
- data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
- data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
- data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
- data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
- data/lib/ruby-prof/call_info.rb +111 -0
- data/lib/ruby-prof/call_info_visitor.rb +40 -0
- data/lib/ruby-prof/compatibility.rb +186 -0
- data/lib/ruby-prof/method_info.rb +109 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
- data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
- data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
- data/lib/ruby-prof/printers/flat_printer.rb +70 -0
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
- data/lib/ruby-prof/printers/graph_printer.rb +116 -0
- data/lib/ruby-prof/printers/multi_printer.rb +58 -0
- data/lib/ruby-prof/profile.rb +22 -0
- data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
- data/lib/ruby-prof/rack.rb +95 -0
- data/lib/ruby-prof/task.rb +147 -0
- data/lib/ruby-prof/thread.rb +35 -0
- data/lib/ruby-prof/version.rb +4 -0
- data/lib/ruby-prof/walker.rb +95 -0
- data/lib/unprof.rb +10 -0
- data/ruby-prof.gemspec +56 -0
- data/test/aggregate_test.rb +136 -0
- data/test/basic_test.rb +128 -0
- data/test/block_test.rb +74 -0
- data/test/call_info_test.rb +78 -0
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/dynamic_method_test.rb +55 -0
- data/test/enumerable_test.rb +21 -0
- data/test/exceptions_test.rb +16 -0
- data/test/exclude_methods_test.rb +146 -0
- data/test/exclude_threads_test.rb +53 -0
- data/test/fiber_test.rb +79 -0
- data/test/issue137_test.rb +63 -0
- data/test/line_number_test.rb +71 -0
- data/test/measure_allocations_test.rb +26 -0
- data/test/measure_cpu_time_test.rb +213 -0
- data/test/measure_gc_runs_test.rb +32 -0
- data/test/measure_gc_time_test.rb +36 -0
- data/test/measure_memory_test.rb +33 -0
- data/test/measure_process_time_test.rb +63 -0
- data/test/measure_wall_time_test.rb +255 -0
- data/test/module_test.rb +45 -0
- data/test/multi_measure_test.rb +38 -0
- data/test/multi_printer_test.rb +83 -0
- data/test/no_method_class_test.rb +15 -0
- data/test/pause_resume_test.rb +166 -0
- data/test/prime.rb +54 -0
- data/test/printers_test.rb +255 -0
- data/test/printing_recursive_graph_test.rb +127 -0
- data/test/rack_test.rb +93 -0
- data/test/recursive_test.rb +212 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +65 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +112 -0
- data/test/test_helper.rb +264 -0
- data/test/thread_test.rb +187 -0
- data/test/unique_call_path_test.rb +202 -0
- data/test/yarv_test.rb +55 -0
- metadata +211 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module RubyProf
|
2
|
+
class Thread
|
3
|
+
def top_methods
|
4
|
+
self.methods.select do |method_info|
|
5
|
+
method_info.call_infos.detect(&:root?)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def top_call_infos
|
10
|
+
top_methods.map(&:call_infos).flatten.select(&:root?)
|
11
|
+
end
|
12
|
+
|
13
|
+
def total_time
|
14
|
+
self.top_methods.inject(0) do |sum, method_info|
|
15
|
+
method_info.call_infos.each do |call_info|
|
16
|
+
if call_info.parent.nil?
|
17
|
+
sum += call_info.total_time
|
18
|
+
end
|
19
|
+
end
|
20
|
+
sum
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
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.call_infos.each do |call_info|
|
29
|
+
sum += call_info.wait_time
|
30
|
+
end
|
31
|
+
sum
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module RubyProf
|
2
|
+
class Walker
|
3
|
+
attr_reader :roots
|
4
|
+
attr_reader :min_fraction
|
5
|
+
|
6
|
+
def initialize(roots, options={})
|
7
|
+
@roots = roots
|
8
|
+
@options = options
|
9
|
+
|
10
|
+
@all_time = @roots.map(&:total_time).inject(0.0, &:+)
|
11
|
+
@min_percent = options[:min_percent] || 2
|
12
|
+
@min_self_percent = options[:min_self_percent] || 0.001
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
around_frame(@roots, :all, "all", 1, 0.0, @all_time) do
|
17
|
+
@roots.each { |r| visit(r) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def enter_frame(type, obj, name, called, elf_value, total_value)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
def leave_frame(type, obj)
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def visit(obj)
|
32
|
+
case obj
|
33
|
+
when RubyProf::Thread then visit_thread(obj)
|
34
|
+
when RubyProf::CallInfo then visit_context(obj)
|
35
|
+
else raise ArgumentError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def visit_thread(th)
|
40
|
+
name = !th.main? ? "Thread ##{th.index}" : "Main Thread"
|
41
|
+
around_frame(th, :thread, name, 1, 0.0, th.total_time) do
|
42
|
+
th.top_call_infos.each { |ci| visit_context(ci) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def visit_context(ci)
|
47
|
+
ctx_stack = []; ctx = ci
|
48
|
+
vis_stack = []; vis = true
|
49
|
+
idx_stack = []; idx = 0
|
50
|
+
|
51
|
+
# Enter the current node.
|
52
|
+
name = ctx.target.source_name
|
53
|
+
enter_frame(:context, ctx, name, ctx.called, ctx.self_time, ctx.total_time)
|
54
|
+
|
55
|
+
# While we still have a call info...
|
56
|
+
while ctx
|
57
|
+
# Does this current node has a child at this index.
|
58
|
+
if (child = ctx.children[idx])
|
59
|
+
# Consume the child at the next index.
|
60
|
+
idx += 1
|
61
|
+
|
62
|
+
total_percent = 100.0 * child.total_time / @all_time.to_f
|
63
|
+
self_percent = 100.0 * child.self_time / ctx.total_time.to_f
|
64
|
+
# Does this meet the minimum requirement to explore?
|
65
|
+
next if total_percent <= @min_percent
|
66
|
+
# Does this span not contain enough information to be useful itself?
|
67
|
+
hide_vis = self_percent <= @min_self_percent
|
68
|
+
# Push the parent onto the stack.
|
69
|
+
# The child becomes the current node.
|
70
|
+
ctx_stack << ctx; ctx = child
|
71
|
+
vis_stack << vis; vis = !hide_vis
|
72
|
+
idx_stack << idx; idx = 0
|
73
|
+
# If visualizing the span, enter it.
|
74
|
+
if vis
|
75
|
+
name = ctx.target.source_name
|
76
|
+
enter_frame(:context, ctx, name, ctx.called, ctx.self_time, ctx.total_time)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
# If we visualized this span, leave it.
|
80
|
+
leave_frame(:context, ctx) if vis
|
81
|
+
# Pop the parent from the stack.
|
82
|
+
ctx = ctx_stack.pop
|
83
|
+
vis = vis_stack.pop
|
84
|
+
idx = idx_stack.pop
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def around_frame(type, obj, name, called, self_value, total_value)
|
90
|
+
enter_frame(type, obj, name, called, self_value, total_value)
|
91
|
+
yield
|
92
|
+
leave_frame(type, obj)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/unprof.rb
ADDED
data/ruby-prof.gemspec
ADDED
@@ -0,0 +1,56 @@
|
|
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 = "airbnb-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
|
+
'examples/*',
|
37
|
+
'ext/ruby_prof/extconf.rb',
|
38
|
+
'ext/ruby_prof/*.c',
|
39
|
+
'ext/ruby_prof/*.h',
|
40
|
+
'ext/ruby_prof/vc/*.sln',
|
41
|
+
'ext/ruby_prof/vc/*.vcxproj',
|
42
|
+
'lib/ruby-prof.rb',
|
43
|
+
'lib/unprof.rb',
|
44
|
+
'lib/ruby-prof/*.rb',
|
45
|
+
'lib/ruby-prof/assets/*.{html,png,erb}',
|
46
|
+
'lib/ruby-prof/profile/*.rb',
|
47
|
+
'lib/ruby-prof/printers/*.rb',
|
48
|
+
'test/*.rb']
|
49
|
+
|
50
|
+
spec.test_files = Dir["test/test_*.rb"]
|
51
|
+
spec.required_ruby_version = '>= 1.9.3'
|
52
|
+
spec.date = Time.now.strftime('%Y-%m-%d')
|
53
|
+
spec.homepage = 'https://github.com/ruby-prof/ruby-prof'
|
54
|
+
spec.add_development_dependency('minitest', '~> 5.8.3')
|
55
|
+
spec.add_development_dependency('rake-compiler')
|
56
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
# Test data
|
7
|
+
# A B C
|
8
|
+
# | | |
|
9
|
+
# Z A A
|
10
|
+
# | |
|
11
|
+
# Z Z
|
12
|
+
|
13
|
+
class AggClass
|
14
|
+
def z
|
15
|
+
sleep 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def a
|
19
|
+
z
|
20
|
+
end
|
21
|
+
|
22
|
+
def b
|
23
|
+
a
|
24
|
+
end
|
25
|
+
|
26
|
+
def c
|
27
|
+
a
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class AggregateTest < TestCase
|
32
|
+
def setup
|
33
|
+
# Need to use wall time for this test due to the sleep calls
|
34
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_all_call_infos_are_not_recursive
|
38
|
+
c1 = AggClass.new
|
39
|
+
result = RubyProf.profile do
|
40
|
+
c1.a
|
41
|
+
c1.b
|
42
|
+
c1.c
|
43
|
+
end
|
44
|
+
methods = result.threads.first.methods.sort.reverse
|
45
|
+
methods.each do |m|
|
46
|
+
m.call_infos.each do |ci|
|
47
|
+
assert(!ci.recursive?)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_call_infos
|
53
|
+
c1 = AggClass.new
|
54
|
+
result = RubyProf.profile do
|
55
|
+
c1.a
|
56
|
+
c1.b
|
57
|
+
c1.c
|
58
|
+
end
|
59
|
+
|
60
|
+
methods = result.threads.first.methods.sort.reverse
|
61
|
+
method = methods.find {|meth| meth.full_name == 'AggClass#z'}
|
62
|
+
|
63
|
+
# Check AggClass#z
|
64
|
+
assert_equal('AggClass#z', method.full_name)
|
65
|
+
assert_equal(3, method.called)
|
66
|
+
assert_in_delta(3, method.total_time, 0.05)
|
67
|
+
assert_in_delta(0, method.wait_time, 0.05)
|
68
|
+
assert_in_delta(0, method.self_time, 0.05)
|
69
|
+
assert_in_delta(3, method.children_time, 0.05)
|
70
|
+
assert_equal(3, method.call_infos.length)
|
71
|
+
|
72
|
+
call_info = method.call_infos[0]
|
73
|
+
assert_equal('AggregateTest#test_call_infos->AggClass#a->AggClass#z', call_info.call_sequence)
|
74
|
+
assert_equal(1, call_info.children.length)
|
75
|
+
|
76
|
+
call_info = method.call_infos[1]
|
77
|
+
assert_equal('AggregateTest#test_call_infos->AggClass#b->AggClass#a->AggClass#z', call_info.call_sequence)
|
78
|
+
assert_equal(1, call_info.children.length)
|
79
|
+
|
80
|
+
call_info = method.call_infos[2]
|
81
|
+
assert_equal('AggregateTest#test_call_infos->AggClass#c->AggClass#a->AggClass#z', call_info.call_sequence)
|
82
|
+
assert_equal(1, call_info.children.length)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_aggregates_parents
|
86
|
+
c1 = AggClass.new
|
87
|
+
result = RubyProf.profile do
|
88
|
+
c1.a
|
89
|
+
c1.b
|
90
|
+
c1.c
|
91
|
+
end
|
92
|
+
|
93
|
+
methods = result.threads.first.methods.sort.reverse
|
94
|
+
method = methods.find {|meth| meth.full_name == 'AggClass#z'}
|
95
|
+
|
96
|
+
# Check AggClass#z
|
97
|
+
assert_equal('AggClass#z', method.full_name)
|
98
|
+
|
99
|
+
call_infos = method.aggregate_parents
|
100
|
+
assert_equal(1, call_infos.length)
|
101
|
+
|
102
|
+
call_info = call_infos.first
|
103
|
+
assert_equal('AggClass#a', call_info.parent.target.full_name)
|
104
|
+
assert_in_delta(3, call_info.total_time, 0.05)
|
105
|
+
assert_in_delta(0, call_info.wait_time, 0.05)
|
106
|
+
assert_in_delta(0, call_info.self_time, 0.05)
|
107
|
+
assert_in_delta(3, call_info.children_time, 0.05)
|
108
|
+
assert_equal(3, call_info.called)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_aggregates_children
|
112
|
+
c1 = AggClass.new
|
113
|
+
result = RubyProf.profile do
|
114
|
+
c1.a
|
115
|
+
c1.b
|
116
|
+
c1.c
|
117
|
+
end
|
118
|
+
|
119
|
+
methods = result.threads.first.methods.sort.reverse
|
120
|
+
method = methods.find {|meth| meth.full_name == 'AggClass#a'}
|
121
|
+
|
122
|
+
# Check AggClass#a
|
123
|
+
assert_equal('AggClass#a', method.full_name)
|
124
|
+
|
125
|
+
call_infos = method.aggregate_children
|
126
|
+
assert_equal(1, call_infos.length)
|
127
|
+
|
128
|
+
call_info = call_infos.first
|
129
|
+
assert_equal('AggClass#z', call_info.target.full_name)
|
130
|
+
assert_in_delta(3, call_info.total_time, 0.05)
|
131
|
+
assert_in_delta(0, call_info.wait_time, 0.05)
|
132
|
+
assert_in_delta(0, call_info.self_time, 0.05)
|
133
|
+
assert_in_delta(3, call_info.children_time, 0.05)
|
134
|
+
assert_equal(3, call_info.called)
|
135
|
+
end
|
136
|
+
end
|
data/test/basic_test.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require File.expand_path('../test_helper', __FILE__)
|
5
|
+
|
6
|
+
class BasicTest < TestCase
|
7
|
+
def setup
|
8
|
+
# Need to use wall time for this test due to the sleep calls
|
9
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
RubyProf.start
|
14
|
+
RubyProf::C1.hello
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_running
|
18
|
+
assert(!RubyProf.running?)
|
19
|
+
RubyProf.start
|
20
|
+
assert(RubyProf.running?)
|
21
|
+
RubyProf.stop
|
22
|
+
assert(!RubyProf.running?)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_double_profile
|
26
|
+
RubyProf.start
|
27
|
+
assert_raises(RuntimeError) do
|
28
|
+
RubyProf.start
|
29
|
+
end
|
30
|
+
RubyProf.stop
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_no_block
|
34
|
+
assert_raises(ArgumentError) do
|
35
|
+
RubyProf.profile
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_traceback
|
40
|
+
RubyProf.start
|
41
|
+
assert_raises(NoMethodError) do
|
42
|
+
RubyProf.xxx
|
43
|
+
end
|
44
|
+
|
45
|
+
RubyProf.stop
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_leave_method
|
49
|
+
start
|
50
|
+
sleep 0.15
|
51
|
+
profile = RubyProf.stop
|
52
|
+
|
53
|
+
assert_equal(1, profile.threads.count)
|
54
|
+
|
55
|
+
thread = profile.threads.first
|
56
|
+
assert_in_delta(0.25, thread.total_time, 0.015)
|
57
|
+
|
58
|
+
top_methods = thread.top_methods.sort
|
59
|
+
assert_equal(2, top_methods.count)
|
60
|
+
assert_equal("BasicTest#start", top_methods[0].full_name)
|
61
|
+
assert_equal("BasicTest#test_leave_method", top_methods[1].full_name)
|
62
|
+
|
63
|
+
assert_equal(4, thread.methods.length)
|
64
|
+
methods = profile.threads.first.methods.sort
|
65
|
+
|
66
|
+
# Check times
|
67
|
+
assert_equal("<Class::RubyProf::C1>#hello", methods[0].full_name)
|
68
|
+
assert_in_delta(0.1, methods[0].total_time, 0.015)
|
69
|
+
assert_in_delta(0.0, methods[0].wait_time, 0.015)
|
70
|
+
assert_in_delta(0.0, methods[0].self_time, 0.015)
|
71
|
+
|
72
|
+
assert_equal("BasicTest#start", methods[1].full_name)
|
73
|
+
assert_in_delta(0.1, methods[1].total_time, 0.015)
|
74
|
+
assert_in_delta(0.0, methods[1].wait_time, 0.015)
|
75
|
+
assert_in_delta(0.0, methods[1].self_time, 0.015)
|
76
|
+
|
77
|
+
assert_equal("BasicTest#test_leave_method", methods[2].full_name)
|
78
|
+
assert_in_delta(0.15, methods[2].total_time, 0.015)
|
79
|
+
assert_in_delta(0.0, methods[2].wait_time, 0.015)
|
80
|
+
assert_in_delta(0.0, methods[2].self_time, 0.015)
|
81
|
+
|
82
|
+
assert_equal("Kernel#sleep", methods[3].full_name)
|
83
|
+
assert_in_delta(0.25, methods[3].total_time, 0.015)
|
84
|
+
assert_in_delta(0.0, methods[3].wait_time, 0.015)
|
85
|
+
assert_in_delta(0.25, methods[3].self_time, 0.015)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_leave_method_2
|
89
|
+
start
|
90
|
+
RubyProf::C1.hello
|
91
|
+
RubyProf::C1.hello
|
92
|
+
profile = RubyProf.stop
|
93
|
+
|
94
|
+
assert_equal(1, profile.threads.count)
|
95
|
+
|
96
|
+
thread = profile.threads.first
|
97
|
+
assert_in_delta(0.3, thread.total_time, 0.015)
|
98
|
+
|
99
|
+
top_methods = thread.top_methods.sort
|
100
|
+
assert_equal(2, top_methods.count)
|
101
|
+
assert_equal("BasicTest#start", top_methods[0].full_name)
|
102
|
+
assert_equal("BasicTest#test_leave_method_2", top_methods[1].full_name)
|
103
|
+
|
104
|
+
assert_equal(4, thread.methods.length)
|
105
|
+
methods = profile.threads.first.methods.sort
|
106
|
+
|
107
|
+
# Check times
|
108
|
+
assert_equal("BasicTest#start", methods[0].full_name)
|
109
|
+
assert_in_delta(0.1, methods[0].total_time, 0.015)
|
110
|
+
assert_in_delta(0.0, methods[0].wait_time, 0.015)
|
111
|
+
assert_in_delta(0.0, methods[0].self_time, 0.015)
|
112
|
+
|
113
|
+
assert_equal("BasicTest#test_leave_method_2", methods[1].full_name)
|
114
|
+
assert_in_delta(0.2, methods[1].total_time, 0.015)
|
115
|
+
assert_in_delta(0.0, methods[1].wait_time, 0.015)
|
116
|
+
assert_in_delta(0.0, methods[1].self_time, 0.015)
|
117
|
+
|
118
|
+
assert_equal("Kernel#sleep", methods[2].full_name)
|
119
|
+
assert_in_delta(0.3, methods[2].total_time, 0.015)
|
120
|
+
assert_in_delta(0.0, methods[2].wait_time, 0.015)
|
121
|
+
assert_in_delta(0.3, methods[2].self_time, 0.015)
|
122
|
+
|
123
|
+
assert_equal("<Class::RubyProf::C1>#hello", methods[3].full_name)
|
124
|
+
assert_in_delta(0.3, methods[3].total_time, 0.015)
|
125
|
+
assert_in_delta(0.0, methods[3].wait_time, 0.015)
|
126
|
+
assert_in_delta(0.0, methods[3].self_time, 0.015)
|
127
|
+
end
|
128
|
+
end
|