ruby-prof 1.1.0-x64-mingw32 → 1.3.0-x64-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.
- checksums.yaml +4 -4
- data/CHANGES +19 -1
- data/bin/ruby-prof +100 -152
- data/ext/ruby_prof/rp_aggregate_call_tree.c +59 -0
- data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
- data/ext/ruby_prof/rp_allocation.c +67 -59
- data/ext/ruby_prof/rp_allocation.h +3 -3
- data/ext/ruby_prof/rp_call_tree.c +369 -0
- data/ext/ruby_prof/rp_call_tree.h +43 -0
- data/ext/ruby_prof/rp_call_trees.c +288 -0
- data/ext/ruby_prof/rp_call_trees.h +28 -0
- data/ext/ruby_prof/rp_measure_allocations.c +11 -13
- data/ext/ruby_prof/rp_measure_process_time.c +11 -13
- data/ext/ruby_prof/rp_measure_wall_time.c +17 -15
- data/ext/ruby_prof/rp_measurement.c +47 -40
- data/ext/ruby_prof/rp_measurement.h +7 -7
- data/ext/ruby_prof/rp_method.c +116 -255
- data/ext/ruby_prof/rp_method.h +31 -39
- data/ext/ruby_prof/rp_profile.c +311 -281
- data/ext/ruby_prof/rp_profile.h +1 -2
- data/ext/ruby_prof/rp_stack.c +113 -105
- data/ext/ruby_prof/rp_stack.h +17 -20
- data/ext/ruby_prof/rp_thread.c +136 -111
- data/ext/ruby_prof/rp_thread.h +12 -9
- data/ext/ruby_prof/ruby_prof.c +27 -23
- data/ext/ruby_prof/ruby_prof.h +9 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -7
- data/lib/ruby-prof.rb +2 -3
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +4 -7
- data/lib/ruby-prof/assets/graph_printer.html.erb +5 -6
- data/lib/ruby-prof/{call_info.rb → call_tree.rb} +6 -6
- data/lib/ruby-prof/call_tree_visitor.rb +36 -0
- data/lib/ruby-prof/measurement.rb +5 -2
- data/lib/ruby-prof/method_info.rb +3 -15
- data/lib/ruby-prof/printers/call_info_printer.rb +12 -10
- data/lib/ruby-prof/printers/call_stack_printer.rb +19 -22
- data/lib/ruby-prof/printers/call_tree_printer.rb +1 -1
- data/lib/ruby-prof/printers/dot_printer.rb +3 -3
- data/lib/ruby-prof/printers/graph_printer.rb +3 -4
- data/lib/ruby-prof/printers/multi_printer.rb +2 -2
- data/lib/ruby-prof/rack.rb +3 -0
- data/lib/ruby-prof/thread.rb +3 -18
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +7 -0
- data/test/alias_test.rb +42 -45
- data/test/basic_test.rb +0 -86
- data/test/{call_info_visitor_test.rb → call_tree_visitor_test.rb} +6 -5
- data/test/call_trees_test.rb +66 -0
- data/test/exclude_methods_test.rb +17 -12
- data/test/fiber_test.rb +197 -9
- data/test/gc_test.rb +36 -42
- data/test/inverse_call_tree_test.rb +175 -0
- data/test/line_number_test.rb +67 -70
- data/test/marshal_test.rb +7 -11
- data/test/measure_allocations_test.rb +224 -234
- data/test/measure_allocations_trace_test.rb +224 -234
- data/test/measure_memory_trace_test.rb +814 -469
- data/test/measure_process_time_test.rb +0 -64
- data/test/measure_times.rb +2 -0
- data/test/measure_wall_time_test.rb +34 -58
- data/test/pause_resume_test.rb +19 -10
- data/test/prime.rb +1 -3
- data/test/prime_script.rb +6 -0
- data/test/printers_test.rb +1 -1
- data/test/recursive_test.rb +50 -54
- data/test/start_stop_test.rb +19 -19
- data/test/test_helper.rb +3 -15
- data/test/thread_test.rb +11 -11
- data/test/unique_call_path_test.rb +25 -95
- metadata +19 -10
- data/ext/ruby_prof/rp_call_info.c +0 -271
- data/ext/ruby_prof/rp_call_info.h +0 -35
- data/lib/2.6.5/ruby_prof.so +0 -0
- data/lib/ruby-prof/call_info_visitor.rb +0 -38
- data/test/parser_timings.rb +0 -24
data/ext/ruby_prof/rp_thread.h
CHANGED
@@ -8,14 +8,14 @@
|
|
8
8
|
#include "rp_stack.h"
|
9
9
|
|
10
10
|
/* Profiling information for a thread. */
|
11
|
-
typedef struct
|
11
|
+
typedef struct thread_data_t
|
12
12
|
{
|
13
13
|
// Runtime
|
14
14
|
VALUE object; /* Cache to wrapped object */
|
15
15
|
VALUE fiber; /* Fiber */
|
16
16
|
prof_stack_t* stack; /* Stack of frames */
|
17
17
|
bool trace; /* Are we tracking this thread */
|
18
|
-
|
18
|
+
prof_call_tree_t* call_tree; /* The root of the call tree*/
|
19
19
|
VALUE thread_id; /* Thread id */
|
20
20
|
VALUE fiber_id; /* Fiber id */
|
21
21
|
VALUE methods; /* Array of RubyProf::MethodInfo */
|
@@ -23,13 +23,16 @@ typedef struct
|
|
23
23
|
} thread_data_t;
|
24
24
|
|
25
25
|
void rp_init_thread(void);
|
26
|
-
st_table
|
27
|
-
thread_data_t
|
28
|
-
thread_data_t* threads_table_insert(void
|
29
|
-
void
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
st_table* threads_table_create(void);
|
27
|
+
thread_data_t* threads_table_lookup(void* profile, VALUE fiber);
|
28
|
+
thread_data_t* threads_table_insert(void* profile, VALUE fiber);
|
29
|
+
void threads_table_free(st_table* table);
|
30
|
+
|
31
|
+
thread_data_t* prof_get_thread(VALUE self);
|
32
|
+
VALUE prof_thread_wrap(thread_data_t* thread);
|
33
|
+
void prof_thread_mark(void* data);
|
34
|
+
|
35
|
+
void switch_thread(void* profile, thread_data_t* thread_data, double measurement);
|
33
36
|
int pause_thread(st_data_t key, st_data_t value, st_data_t data);
|
34
37
|
int unpause_thread(st_data_t key, st_data_t value, st_data_t data);
|
35
38
|
|
data/ext/ruby_prof/ruby_prof.c
CHANGED
@@ -1,34 +1,36 @@
|
|
1
1
|
/* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
2
|
Please see the LICENSE file for copyright and distribution information */
|
3
3
|
|
4
|
-
/* ruby-prof tracks the time spent executing every method in ruby programming.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
*/
|
4
|
+
/* ruby-prof tracks the time spent executing every method in ruby programming.
|
5
|
+
The main players are:
|
6
|
+
|
7
|
+
profile_t - This represents 1 profile.
|
8
|
+
thread_data_t - Stores data about a single thread.
|
9
|
+
prof_stack_t - The method call stack in a particular thread
|
10
|
+
prof_method_t - Profiling information about each method
|
11
|
+
prof_call_tree_t - Keeps track a method's callers and callees.
|
12
|
+
|
13
|
+
The final result is an instance of a profile object which has a hash table of
|
14
|
+
thread_data_t, keyed on the thread id. Each thread in turn has a hash table
|
15
|
+
of prof_method_t, keyed on the method id. A hash table is used for quick
|
16
|
+
look up when doing a profile. However, it is exposed to Ruby as an array.
|
17
|
+
|
18
|
+
Each prof_method_t has two hash tables, parent and children, of prof_call_tree_t.
|
19
|
+
These objects keep track of a method's callers (who called the method) and its
|
20
|
+
callees (who the method called). These are keyed the method id, but once again,
|
21
|
+
are exposed to Ruby as arrays. Each prof_call_into_t maintains a pointer to the
|
22
|
+
caller or callee method, thereby making it easy to navigate through the call
|
23
|
+
hierarchy in ruby - which is very helpful for creating call graphs.
|
24
|
+
*/
|
25
25
|
|
26
26
|
#include "ruby_prof.h"
|
27
27
|
|
28
28
|
#include "rp_allocation.h"
|
29
29
|
#include "rp_measurement.h"
|
30
30
|
#include "rp_method.h"
|
31
|
-
#include "
|
31
|
+
#include "rp_call_tree.h"
|
32
|
+
#include "rp_aggregate_call_tree.h"
|
33
|
+
#include "rp_call_trees.h"
|
32
34
|
#include "rp_profile.h"
|
33
35
|
#include "rp_stack.h"
|
34
36
|
#include "rp_thread.h"
|
@@ -40,7 +42,9 @@ void Init_ruby_prof()
|
|
40
42
|
mProf = rb_define_module("RubyProf");
|
41
43
|
|
42
44
|
rp_init_allocation();
|
43
|
-
|
45
|
+
rp_init_call_tree();
|
46
|
+
rp_init_aggregate_call_tree();
|
47
|
+
rp_init_call_trees();
|
44
48
|
rp_init_measure();
|
45
49
|
rp_init_method_info();
|
46
50
|
rp_init_profile();
|
data/ext/ruby_prof/ruby_prof.h
CHANGED
@@ -9,6 +9,15 @@
|
|
9
9
|
#include <stdio.h>
|
10
10
|
#include <stdbool.h>
|
11
11
|
|
12
|
+
#ifndef rb_st_lookup
|
13
|
+
#define rb_st_foreach st_foreach
|
14
|
+
#define rb_st_free_table st_free_table
|
15
|
+
#define rb_st_init_numtable st_init_numtable
|
16
|
+
#define rb_st_insert st_insert
|
17
|
+
#define rb_st_lookup st_lookup
|
18
|
+
#endif
|
19
|
+
|
20
|
+
|
12
21
|
extern VALUE mProf;
|
13
22
|
|
14
23
|
// This method is not exposed in Ruby header files - at least not as of Ruby 2.6.3 :(
|
@@ -64,7 +64,7 @@
|
|
64
64
|
</PropertyGroup>
|
65
65
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
66
66
|
<TargetExt>.so</TargetExt>
|
67
|
-
<OutDir
|
67
|
+
<OutDir>..\..\..\lib</OutDir>
|
68
68
|
</PropertyGroup>
|
69
69
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
70
70
|
<ClCompile>
|
@@ -102,30 +102,34 @@
|
|
102
102
|
</ItemDefinitionGroup>
|
103
103
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
104
104
|
<ClCompile>
|
105
|
-
<AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.
|
105
|
+
<AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.7.0vc\include\ruby-2.7.0\x64-mswin64_140;C:\msys64\usr\local\ruby-2.7.0vc\include\ruby-2.7.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
106
106
|
<Optimization>Disabled</Optimization>
|
107
107
|
<PreprocessorDefinitions>HAVE_RB_TRACEARG_CALLEE_ID;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
108
108
|
</ClCompile>
|
109
109
|
<Link>
|
110
|
-
<AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.
|
111
|
-
<AdditionalDependencies>x64-vcruntime140-
|
110
|
+
<AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.7.0vc\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
111
|
+
<AdditionalDependencies>x64-vcruntime140-ruby270.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
112
112
|
<ModuleDefinitionFile>ruby_prof.def</ModuleDefinitionFile>
|
113
|
+
<SubSystem>Console</SubSystem>
|
113
114
|
</Link>
|
114
115
|
</ItemDefinitionGroup>
|
115
116
|
<ItemGroup>
|
117
|
+
<ClInclude Include="..\rp_aggregate_call_tree.h" />
|
116
118
|
<ClInclude Include="..\rp_allocation.h" />
|
117
|
-
<ClInclude Include="..\
|
119
|
+
<ClInclude Include="..\rp_call_tree.h" />
|
120
|
+
<ClInclude Include="..\rp_call_trees.h" />
|
118
121
|
<ClInclude Include="..\rp_measurement.h" />
|
119
122
|
<ClInclude Include="..\rp_method.h" />
|
120
123
|
<ClInclude Include="..\rp_profile.h" />
|
121
124
|
<ClInclude Include="..\rp_stack.h" />
|
122
125
|
<ClInclude Include="..\rp_thread.h" />
|
123
126
|
<ClInclude Include="..\ruby_prof.h" />
|
124
|
-
<ClInclude Include="..\version.h" />
|
125
127
|
</ItemGroup>
|
126
128
|
<ItemGroup>
|
129
|
+
<ClCompile Include="..\rp_aggregate_call_tree.c" />
|
127
130
|
<ClCompile Include="..\rp_allocation.c" />
|
128
|
-
<ClCompile Include="..\
|
131
|
+
<ClCompile Include="..\rp_call_tree.c" />
|
132
|
+
<ClCompile Include="..\rp_call_trees.c" />
|
129
133
|
<ClCompile Include="..\rp_measurement.c" />
|
130
134
|
<ClCompile Include="..\rp_measure_allocations.c" />
|
131
135
|
<ClCompile Include="..\rp_measure_memory.c" />
|
data/lib/ruby-prof.rb
CHANGED
@@ -9,7 +9,7 @@ rescue LoadError
|
|
9
9
|
end
|
10
10
|
|
11
11
|
require 'ruby-prof/version'
|
12
|
-
require 'ruby-prof/
|
12
|
+
require 'ruby-prof/call_tree'
|
13
13
|
require 'ruby-prof/compatibility'
|
14
14
|
require 'ruby-prof/measurement'
|
15
15
|
require 'ruby-prof/method_info'
|
@@ -18,8 +18,7 @@ require 'ruby-prof/rack'
|
|
18
18
|
require 'ruby-prof/thread'
|
19
19
|
|
20
20
|
module RubyProf
|
21
|
-
autoload :
|
22
|
-
|
21
|
+
autoload :CallTreeVisitor, 'ruby-prof/call_tree_visitor'
|
23
22
|
autoload :AbstractPrinter, 'ruby-prof/printers/abstract_printer'
|
24
23
|
autoload :CallInfoPrinter, 'ruby-prof/printers/call_info_printer'
|
25
24
|
autoload :CallStackPrinter, 'ruby-prof/printers/call_stack_printer'
|
@@ -697,13 +697,10 @@
|
|
697
697
|
<div class="thread">
|
698
698
|
<span>Thread: <%= thread.id %>, Fiber: <%= thread.fiber_id %> (<%= thread_info %>)</span>
|
699
699
|
<ul name="thread">
|
700
|
-
<%
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
print_stack(output, visited, call_info, call_info.total_time) %>
|
705
|
-
<%= output.string %>
|
706
|
-
<% end %>
|
700
|
+
<% visited = Set.new
|
701
|
+
output = StringIO.new('')
|
702
|
+
print_stack(output, visited, thread.call_tree, thread.call_tree.total_time) %>
|
703
|
+
<%= output.string %>
|
707
704
|
</ul>
|
708
705
|
</div>
|
709
706
|
<% end %>
|
@@ -217,8 +217,7 @@
|
|
217
217
|
self_percentage = (method.self_time/total_time) * 100 %>
|
218
218
|
|
219
219
|
<!-- Parents -->
|
220
|
-
<% for caller in method.callers.sort
|
221
|
-
next if method.root?
|
220
|
+
<% for caller in method.call_trees.callers.sort
|
222
221
|
next if min_time && caller.total_time < min_time %>
|
223
222
|
<tr>
|
224
223
|
<td> </td>
|
@@ -228,12 +227,12 @@
|
|
228
227
|
<td><%= sprintf("%.2f", caller.wait_time) %></td>
|
229
228
|
<td><%= sprintf("%.2f", caller.children_time) %></td>
|
230
229
|
<td><%= "#{caller.called}/#{method.called}" %></td>
|
231
|
-
<td class="method_name"><%= create_link(thread, total_time, caller.parent) %></td>
|
230
|
+
<td class="method_name"><%= create_link(thread, total_time, caller.parent.target) %></td>
|
232
231
|
<% if @result.track_allocations? %>
|
233
232
|
<td>-</td>
|
234
233
|
<% end %>
|
235
|
-
<td><%= if caller.parent.source_file
|
236
|
-
file_link(caller.parent.source_file, caller.line)
|
234
|
+
<td><%= if caller.parent.target.source_file
|
235
|
+
file_link(caller.parent.target.source_file, caller.line)
|
237
236
|
end %></td>
|
238
237
|
</tr>
|
239
238
|
<% end %>
|
@@ -293,7 +292,7 @@
|
|
293
292
|
<% end %>
|
294
293
|
|
295
294
|
<!-- Children -->
|
296
|
-
<% for callee in method.callees.sort_by(&:total_time).reverse
|
295
|
+
<% for callee in method.call_trees.callees.sort_by(&:total_time).reverse
|
297
296
|
next if min_time && callee.total_time < min_time %>
|
298
297
|
<tr>
|
299
298
|
<td> </td>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module RubyProf
|
4
|
-
# The
|
4
|
+
# The CallTree class is used to track the relationships between methods. It is a helper class used by
|
5
5
|
# RubyProf::MethodInfo to keep track of which methods called a given method and which methods a given
|
6
|
-
# method called. Each
|
6
|
+
# method called. Each CallTree has a parent and target method. You cannot create a CallTree object directly,
|
7
7
|
# they are generated while running a profile.
|
8
|
-
class
|
8
|
+
class CallTree
|
9
9
|
# The number of times the parent method called the target method
|
10
10
|
def called
|
11
11
|
self.measurement.called
|
@@ -31,7 +31,7 @@ module RubyProf
|
|
31
31
|
self.total_time - self.self_time - self.wait_time
|
32
32
|
end
|
33
33
|
|
34
|
-
# Compares two
|
34
|
+
# Compares two CallTree instances. The comparison is based on the CallTree#parent, CallTree#target,
|
35
35
|
# and total time.
|
36
36
|
def <=>(other)
|
37
37
|
if self.target == other.target && self.parent == other.parent
|
@@ -47,11 +47,11 @@ module RubyProf
|
|
47
47
|
|
48
48
|
# :nodoc:
|
49
49
|
def to_s
|
50
|
-
"
|
50
|
+
"<#{self.class.name} - #{self.target.full_name}>"
|
51
51
|
end
|
52
52
|
|
53
53
|
def inspect
|
54
|
-
|
54
|
+
self.to_s
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RubyProf
|
2
|
+
# The call info visitor class does a depth-first traversal across a
|
3
|
+
# list of call infos. At each call_tree node, the visitor executes
|
4
|
+
# the block provided in the #visit method. The block is passed two
|
5
|
+
# parameters, the event and the call_tree instance. Event will be
|
6
|
+
# either :enter or :exit.
|
7
|
+
#
|
8
|
+
# visitor = RubyProf::CallTreeVisitor.new(result.threads.first.call_tree)
|
9
|
+
#
|
10
|
+
# method_names = Array.new
|
11
|
+
#
|
12
|
+
# visitor.visit do |call_tree, event|
|
13
|
+
# method_names << call_tree.target.full_name if event == :enter
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# puts method_names
|
17
|
+
class CallTreeVisitor
|
18
|
+
def initialize(call_tree)
|
19
|
+
@call_tree = call_tree
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit(&block)
|
23
|
+
visit_call_tree(@call_tree, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def visit_call_tree(call_tree, &block)
|
29
|
+
yield call_tree, :enter
|
30
|
+
call_tree.children.each do |child|
|
31
|
+
visit_call_tree(child, &block)
|
32
|
+
end
|
33
|
+
yield call_tree, :exit
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module RubyProf
|
2
2
|
# The Measurement class is a helper class used by RubyProf::MethodInfo to store information about the method.
|
3
|
-
# You cannot create a
|
3
|
+
# You cannot create a CallTree object directly, they are generated while running a profile.
|
4
4
|
class Measurement
|
5
|
-
|
5
|
+
def children_time
|
6
|
+
self.total_time - self.self_time - self.wait_time
|
7
|
+
end
|
8
|
+
|
6
9
|
def to_s
|
7
10
|
"c: #{called}, tt: #{total_time}, st: #{self_time}"
|
8
11
|
end
|
@@ -52,14 +52,9 @@ module RubyProf
|
|
52
52
|
self.total_time - self.self_time - self.wait_time
|
53
53
|
end
|
54
54
|
|
55
|
-
# The min call depth of this method
|
56
|
-
def min_depth
|
57
|
-
@min_depth ||= callers.map(&:depth).min
|
58
|
-
end
|
59
|
-
|
60
55
|
# :enddoc:
|
61
56
|
def <=>(other)
|
62
|
-
if other
|
57
|
+
if other.nil?
|
63
58
|
-1
|
64
59
|
elsif self.full_name == other.full_name
|
65
60
|
0
|
@@ -67,9 +62,9 @@ module RubyProf
|
|
67
62
|
-1
|
68
63
|
elsif self.total_time > other.total_time
|
69
64
|
1
|
70
|
-
elsif self.min_depth < other.min_depth
|
65
|
+
elsif self.call_trees.min_depth < other.call_trees.min_depth
|
71
66
|
1
|
72
|
-
elsif self.min_depth > other.min_depth
|
67
|
+
elsif self.call_trees.min_depth > other.call_trees.min_depth
|
73
68
|
-1
|
74
69
|
else
|
75
70
|
self.full_name <=> other.full_name
|
@@ -79,12 +74,5 @@ module RubyProf
|
|
79
74
|
def to_s
|
80
75
|
"#{self.full_name} (c: #{self.called}, tt: #{self.total_time}, st: #{self.self_time}, wt: #{wait_time}, ct: #{self.children_time})"
|
81
76
|
end
|
82
|
-
|
83
|
-
# Remove method from the call graph. should not be called directly.
|
84
|
-
def eliminate!
|
85
|
-
# $stderr.puts "eliminating #{self}"
|
86
|
-
callers.each{ |call_info| call_info.eliminate! }
|
87
|
-
callers.clear
|
88
|
-
end
|
89
77
|
end
|
90
78
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module RubyProf
|
4
|
-
# Prints out the call graph based on
|
4
|
+
# Prints out the call graph based on CallTree instances. This
|
5
5
|
# is mainly for debugging purposes as it provides access into
|
6
6
|
# into RubyProf's internals.
|
7
7
|
#
|
@@ -19,6 +19,7 @@ module RubyProf
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def print_header(thread)
|
22
|
+
@output << "----------------------------------------------------\n"
|
22
23
|
@output << "Thread ID: #{thread.id}\n"
|
23
24
|
@output << "Fiber ID: #{thread.fiber_id}\n"
|
24
25
|
@output << "Total Time: #{thread.total_time}\n"
|
@@ -27,18 +28,18 @@ module RubyProf
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def print_methods(thread)
|
30
|
-
visitor =
|
31
|
+
visitor = CallTreeVisitor.new(thread.call_tree)
|
31
32
|
|
32
|
-
visitor.visit do |
|
33
|
+
visitor.visit do |call_tree, event|
|
33
34
|
if event == :enter
|
34
|
-
@output << " " *
|
35
|
-
@output <<
|
35
|
+
@output << " " * call_tree.depth
|
36
|
+
@output << call_tree.target.full_name
|
36
37
|
@output << " ("
|
37
|
-
@output << "tt:#{sprintf("%#{TIME_WIDTH}.2f",
|
38
|
-
@output << "st:#{sprintf("%#{TIME_WIDTH}.2f",
|
39
|
-
@output << "wt:#{sprintf("%#{TIME_WIDTH}.2f",
|
40
|
-
@output << "ct:#{sprintf("%#{TIME_WIDTH}.2f",
|
41
|
-
@output << "call:#{
|
38
|
+
@output << "tt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.total_time)}, "
|
39
|
+
@output << "st:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.self_time)}, "
|
40
|
+
@output << "wt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.wait_time)}, "
|
41
|
+
@output << "ct:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.children_time)}, "
|
42
|
+
@output << "call:#{call_tree.called}, "
|
42
43
|
@output << ")"
|
43
44
|
@output << "\n"
|
44
45
|
end
|
@@ -46,6 +47,7 @@ module RubyProf
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def print_footer(thread)
|
50
|
+
@output << "\n" << "\n"
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -46,7 +46,6 @@ module RubyProf
|
|
46
46
|
def print(output = STDOUT, options = {})
|
47
47
|
setup_options(options)
|
48
48
|
output << @erb.result(binding)
|
49
|
-
a = 1
|
50
49
|
end
|
51
50
|
|
52
51
|
# :enddoc:
|
@@ -55,50 +54,49 @@ module RubyProf
|
|
55
54
|
@erb = ERB.new(self.template)
|
56
55
|
end
|
57
56
|
|
58
|
-
def print_stack(output, visited,
|
59
|
-
total_time =
|
57
|
+
def print_stack(output, visited, call_tree, parent_time)
|
58
|
+
total_time = call_tree.total_time
|
60
59
|
percent_parent = (total_time/parent_time)*100
|
61
60
|
percent_total = (total_time/@overall_time)*100
|
62
61
|
return unless percent_total > min_percent
|
63
62
|
color = self.color(percent_total)
|
64
|
-
kids = call_info.target.callees
|
65
63
|
visible = percent_total >= threshold
|
66
64
|
expanded = percent_total >= expansion
|
67
65
|
display = visible ? "block" : "none"
|
68
66
|
|
69
67
|
output << "<li class=\"color#{color}\" style=\"display:#{display}\">" << "\n"
|
70
68
|
|
71
|
-
if visited.include?(
|
69
|
+
if visited.include?(call_tree)
|
72
70
|
output << "<a href=\"#\" class=\"toggle empty\" ></a>" << "\n"
|
73
|
-
output << "<span>%s %s</span>" % [link(
|
71
|
+
output << "<span>%s %s</span>" % [link(call_tree.target, true), graph_link(call_tree)] << "\n"
|
74
72
|
else
|
75
|
-
visited <<
|
73
|
+
visited << call_tree
|
76
74
|
|
77
|
-
if
|
75
|
+
if call_tree.children.empty?
|
78
76
|
output << "<a href=\"#\" class=\"toggle empty\" ></a>" << "\n"
|
79
77
|
else
|
80
|
-
visible_children =
|
78
|
+
visible_children = call_tree.children.any?{|ci| (ci.total_time/@overall_time)*100 >= threshold}
|
81
79
|
image = visible_children ? (expanded ? "minus" : "plus") : "empty"
|
82
80
|
output << "<a href=\"#\" class=\"toggle #{image}\" ></a>" << "\n"
|
83
81
|
end
|
84
82
|
output << "<span>%4.2f%% (%4.2f%%) %s %s</span>" % [percent_total, percent_parent,
|
85
|
-
link(
|
83
|
+
link(call_tree.target, false), graph_link(call_tree)] << "\n"
|
86
84
|
|
87
|
-
unless
|
85
|
+
unless call_tree.children.empty?
|
88
86
|
output << (expanded ? '<ul>' : '<ul style="display:none">') << "\n"
|
89
|
-
|
90
|
-
print_stack(output, visited,
|
87
|
+
call_tree.children.sort_by{|c| -c.total_time}.each do |child_call_tree|
|
88
|
+
print_stack(output, visited, child_call_tree, total_time)
|
91
89
|
end
|
92
90
|
output << '</ul>' << "\n"
|
93
91
|
end
|
94
92
|
|
95
|
-
visited.delete(
|
93
|
+
visited.delete(call_tree)
|
96
94
|
end
|
97
95
|
output << '</li>' << "\n"
|
98
96
|
end
|
99
97
|
|
100
|
-
def name(
|
101
|
-
method =
|
98
|
+
def name(call_tree)
|
99
|
+
method = call_tree.target
|
102
100
|
method.full_name
|
103
101
|
end
|
104
102
|
|
@@ -112,19 +110,18 @@ module RubyProf
|
|
112
110
|
end
|
113
111
|
end
|
114
112
|
|
115
|
-
def graph_link(
|
116
|
-
total_calls =
|
117
|
-
href = "#{method_href(call_info.target)}"
|
113
|
+
def graph_link(call_tree)
|
114
|
+
total_calls = call_tree.target.called
|
118
115
|
totals = total_calls.to_s
|
119
|
-
"[#{
|
116
|
+
"[#{call_tree.called} calls, #{totals} total]"
|
120
117
|
end
|
121
118
|
|
122
119
|
def method_href(method)
|
123
120
|
h(method.full_name.gsub(/[><#\.\?=:]/,"_"))
|
124
121
|
end
|
125
122
|
|
126
|
-
def total_time(
|
127
|
-
sum(
|
123
|
+
def total_time(call_trees)
|
124
|
+
sum(call_trees.map{|ci| ci.total_time})
|
128
125
|
end
|
129
126
|
|
130
127
|
def sum(a)
|