ruby-prof 1.6.3 → 1.7.2
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 -0
- data/ext/ruby_prof/extconf.rb +23 -22
- data/ext/ruby_prof/rp_allocation.c +342 -342
- data/ext/ruby_prof/rp_call_tree.c +1 -1
- data/ext/ruby_prof/rp_call_tree.h +1 -1
- data/ext/ruby_prof/rp_call_trees.c +296 -296
- data/ext/ruby_prof/rp_call_trees.h +28 -28
- data/ext/ruby_prof/rp_measure_allocations.c +47 -47
- data/ext/ruby_prof/rp_measure_memory.c +46 -46
- data/ext/ruby_prof/rp_measure_process_time.c +64 -66
- data/ext/ruby_prof/rp_measure_wall_time.c +52 -64
- data/ext/ruby_prof/rp_measurement.c +364 -364
- data/ext/ruby_prof/rp_method.c +551 -550
- data/ext/ruby_prof/rp_method.h +5 -2
- data/ext/ruby_prof/rp_profile.c +2 -2
- data/ext/ruby_prof/rp_profile.h +36 -36
- data/ext/ruby_prof/rp_stack.c +212 -212
- data/ext/ruby_prof/rp_thread.c +1 -1
- data/ext/ruby_prof/ruby_prof.c +50 -50
- data/ext/ruby_prof/ruby_prof.h +35 -34
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +5 -7
- data/lib/ruby-prof/compatibility.rb +113 -113
- data/lib/ruby-prof/exclude_common_methods.rb +204 -198
- data/lib/ruby-prof/method_info.rb +87 -85
- data/lib/ruby-prof/printers/abstract_printer.rb +156 -138
- data/lib/ruby-prof/version.rb +3 -3
- data/ruby-prof.gemspec +66 -64
- data/test/dynamic_method_test.rb +9 -21
- data/test/enumerable_test.rb +23 -21
- data/test/exclude_methods_test.rb +363 -146
- data/test/fiber_test.rb +195 -195
- data/test/gc_test.rb +104 -102
- data/test/line_number_test.rb +426 -134
- data/test/measure_allocations_test.rb +1172 -660
- data/test/measure_memory_test.rb +1193 -1024
- data/test/measure_process_time_test.rb +3330 -1610
- data/test/measure_wall_time_test.rb +634 -420
- data/test/merge_test.rb +146 -146
- data/test/method_info_test.rb +100 -95
- data/test/printers_test.rb +178 -135
- data/test/recursive_test.rb +796 -425
- data/test/start_stop_test.rb +4 -4
- data/test/test_helper.rb +20 -20
- data/test/thread_test.rb +229 -235
- data/test/unique_call_path_test.rb +9 -22
- data/test/yarv_test.rb +1 -5
- metadata +33 -8
|
@@ -1,198 +1,204 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
|
|
3
|
-
# :enddoc:
|
|
4
|
-
module RubyProf
|
|
5
|
-
module ExcludeCommonMethods
|
|
6
|
-
ENUMERABLE_NAMES = Enumerable.instance_methods(false)
|
|
7
|
-
|
|
8
|
-
def self.apply!(profile)
|
|
9
|
-
##
|
|
10
|
-
# Kernel Methods
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
exclude_methods(profile, Kernel, [
|
|
14
|
-
:dup,
|
|
15
|
-
:initialize_dup,
|
|
16
|
-
:tap,
|
|
17
|
-
:send,
|
|
18
|
-
:public_send,
|
|
19
|
-
])
|
|
20
|
-
|
|
21
|
-
##
|
|
22
|
-
# Fundamental Types
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
exclude_methods(profile, BasicObject,
|
|
26
|
-
exclude_methods(profile,
|
|
27
|
-
exclude_methods(profile,
|
|
28
|
-
exclude_methods(profile,
|
|
29
|
-
exclude_methods(profile,
|
|
30
|
-
exclude_methods(profile,
|
|
31
|
-
exclude_methods(profile,
|
|
32
|
-
|
|
33
|
-
##
|
|
34
|
-
# Value Types
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
exclude_methods(profile,
|
|
38
|
-
:
|
|
39
|
-
:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
exclude_enumerable(profile,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
:
|
|
63
|
-
:
|
|
64
|
-
:
|
|
65
|
-
:
|
|
66
|
-
:
|
|
67
|
-
:
|
|
68
|
-
:
|
|
69
|
-
:
|
|
70
|
-
:
|
|
71
|
-
:
|
|
72
|
-
:
|
|
73
|
-
:
|
|
74
|
-
:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
:
|
|
79
|
-
:
|
|
80
|
-
:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
:
|
|
85
|
-
:
|
|
86
|
-
:
|
|
87
|
-
:
|
|
88
|
-
:
|
|
89
|
-
:
|
|
90
|
-
:
|
|
91
|
-
:
|
|
92
|
-
:
|
|
93
|
-
:
|
|
94
|
-
:
|
|
95
|
-
:
|
|
96
|
-
:
|
|
97
|
-
:
|
|
98
|
-
:
|
|
99
|
-
:
|
|
100
|
-
:
|
|
101
|
-
:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
:
|
|
106
|
-
:
|
|
107
|
-
:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
:
|
|
112
|
-
:
|
|
113
|
-
:
|
|
114
|
-
:
|
|
115
|
-
:
|
|
116
|
-
:
|
|
117
|
-
:
|
|
118
|
-
:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
##
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if defined?(NewRelic::Agent::
|
|
153
|
-
exclude_methods(profile, NewRelic::Agent::
|
|
154
|
-
:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
end
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
# :enddoc:
|
|
4
|
+
module RubyProf
|
|
5
|
+
module ExcludeCommonMethods
|
|
6
|
+
ENUMERABLE_NAMES = Enumerable.instance_methods(false)
|
|
7
|
+
|
|
8
|
+
def self.apply!(profile)
|
|
9
|
+
##
|
|
10
|
+
# Kernel Methods
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
exclude_methods(profile, Kernel, [
|
|
14
|
+
:dup,
|
|
15
|
+
:initialize_dup,
|
|
16
|
+
:tap,
|
|
17
|
+
:send,
|
|
18
|
+
:public_send,
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Fundamental Types
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
exclude_methods(profile, BasicObject, :!=)
|
|
26
|
+
exclude_methods(profile, Kernel, :"block_given?")
|
|
27
|
+
exclude_methods(profile, Method, :[])
|
|
28
|
+
exclude_methods(profile, Module, :new)
|
|
29
|
+
exclude_methods(profile, Class, :new)
|
|
30
|
+
exclude_methods(profile, Proc, :call, :yield)
|
|
31
|
+
exclude_methods(profile, Range, :each)
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Value Types
|
|
35
|
+
##
|
|
36
|
+
|
|
37
|
+
exclude_methods(profile, Integer, [
|
|
38
|
+
:times,
|
|
39
|
+
:succ,
|
|
40
|
+
:<
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
exclude_methods(profile, String, [
|
|
44
|
+
:sub,
|
|
45
|
+
:sub!,
|
|
46
|
+
:gsub,
|
|
47
|
+
:gsub!,
|
|
48
|
+
])
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# Emumerables
|
|
52
|
+
##
|
|
53
|
+
|
|
54
|
+
exclude_enumerable(profile, Enumerable)
|
|
55
|
+
exclude_enumerable(profile, Enumerator)
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# Collections
|
|
59
|
+
##
|
|
60
|
+
|
|
61
|
+
exclude_enumerable(profile, Array, [
|
|
62
|
+
:each_index,
|
|
63
|
+
:map!,
|
|
64
|
+
:select!,
|
|
65
|
+
:reject!,
|
|
66
|
+
:collect!,
|
|
67
|
+
:sort!,
|
|
68
|
+
:sort_by!,
|
|
69
|
+
:index,
|
|
70
|
+
:delete_if,
|
|
71
|
+
:keep_if,
|
|
72
|
+
:drop_while,
|
|
73
|
+
:uniq,
|
|
74
|
+
:uniq!,
|
|
75
|
+
:"==",
|
|
76
|
+
:eql?,
|
|
77
|
+
:hash,
|
|
78
|
+
:to_json,
|
|
79
|
+
:as_json,
|
|
80
|
+
:encode_json,
|
|
81
|
+
])
|
|
82
|
+
|
|
83
|
+
exclude_enumerable(profile, Hash, [
|
|
84
|
+
:dup,
|
|
85
|
+
:initialize_dup,
|
|
86
|
+
:fetch,
|
|
87
|
+
:"[]",
|
|
88
|
+
:"[]=",
|
|
89
|
+
:each_key,
|
|
90
|
+
:each_value,
|
|
91
|
+
:each_pair,
|
|
92
|
+
:map!,
|
|
93
|
+
:select!,
|
|
94
|
+
:reject!,
|
|
95
|
+
:collect!,
|
|
96
|
+
:delete_if,
|
|
97
|
+
:keep_if,
|
|
98
|
+
:slice,
|
|
99
|
+
:slice!,
|
|
100
|
+
:except,
|
|
101
|
+
:except!,
|
|
102
|
+
:"==",
|
|
103
|
+
:eql?,
|
|
104
|
+
:hash,
|
|
105
|
+
:to_json,
|
|
106
|
+
:as_json,
|
|
107
|
+
:encode_json,
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
exclude_enumerable(profile, Set, [
|
|
111
|
+
:map!,
|
|
112
|
+
:select!,
|
|
113
|
+
:reject!,
|
|
114
|
+
:collect!,
|
|
115
|
+
:classify,
|
|
116
|
+
:delete_if,
|
|
117
|
+
:keep_if,
|
|
118
|
+
:divide,
|
|
119
|
+
:"==",
|
|
120
|
+
:eql?,
|
|
121
|
+
:hash,
|
|
122
|
+
:to_json,
|
|
123
|
+
:as_json,
|
|
124
|
+
:encode_json,
|
|
125
|
+
])
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Garbage Collection
|
|
129
|
+
##
|
|
130
|
+
|
|
131
|
+
exclude_singleton_methods(profile, GC, [
|
|
132
|
+
:start
|
|
133
|
+
])
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
# Unicorn
|
|
137
|
+
##
|
|
138
|
+
|
|
139
|
+
if defined?(Unicorn)
|
|
140
|
+
exclude_methods(profile, Unicorn::HttpServer, :process_client)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
if defined?(Unicorn::OobGC)
|
|
144
|
+
exclude_methods(profile, Unicorn::OobGC, :process_client)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# New Relic
|
|
149
|
+
##
|
|
150
|
+
|
|
151
|
+
if defined?(NewRelic::Agent)
|
|
152
|
+
if defined?(NewRelic::Agent::Instrumentation::MiddlewareTracing)
|
|
153
|
+
exclude_methods(profile, NewRelic::Agent::Instrumentation::MiddlewareTracing, [
|
|
154
|
+
:call
|
|
155
|
+
])
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
if defined?(NewRelic::Agent::MethodTracerHelpers)
|
|
159
|
+
exclude_methods(profile, NewRelic::Agent::MethodTracerHelpers, [
|
|
160
|
+
:trace_execution_scoped,
|
|
161
|
+
:log_errors,
|
|
162
|
+
])
|
|
163
|
+
|
|
164
|
+
exclude_singleton_methods(profile, NewRelic::Agent::MethodTracerHelpers, [
|
|
165
|
+
:trace_execution_scoped,
|
|
166
|
+
:log_errors,
|
|
167
|
+
])
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if defined?(NewRelic::Agent::MethodTracer)
|
|
171
|
+
exclude_methods(profile, NewRelic::Agent::MethodTracer, [
|
|
172
|
+
:trace_execution_scoped,
|
|
173
|
+
:trace_execution_unscoped,
|
|
174
|
+
])
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
##
|
|
179
|
+
# Miscellaneous Methods
|
|
180
|
+
##
|
|
181
|
+
|
|
182
|
+
if defined?(Mustache)
|
|
183
|
+
exclude_methods(profile, Mustache::Context, [
|
|
184
|
+
:fetch
|
|
185
|
+
])
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
private
|
|
190
|
+
|
|
191
|
+
def self.exclude_enumerable(profile, mod, *method_or_methods)
|
|
192
|
+
exclude_methods(profile, mod, [:each, *method_or_methods])
|
|
193
|
+
exclude_methods(profile, mod, ENUMERABLE_NAMES)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def self.exclude_methods(profile, mod, *method_or_methods)
|
|
197
|
+
profile.exclude_methods!(mod, method_or_methods)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def self.exclude_singleton_methods(profile, mod, *method_or_methods)
|
|
201
|
+
profile.exclude_singleton_methods!(mod, method_or_methods)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
@@ -1,85 +1,87 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
module RubyProf
|
|
4
|
-
# The MethodInfo class is used to track information about each method that is profiled.
|
|
5
|
-
# You cannot create a MethodInfo object directly, they are generated while running a profile.
|
|
6
|
-
class MethodInfo
|
|
7
|
-
include Comparable
|
|
8
|
-
|
|
9
|
-
# Returns the full name of a class. The interpretation of method names is:
|
|
10
|
-
#
|
|
11
|
-
# * MyObject#test - An method defined in a class
|
|
12
|
-
# * <Class:MyObject>#test - A method defined in a singleton class.
|
|
13
|
-
# * <Module:MyObject>#test - A method defined in a singleton module.
|
|
14
|
-
# * <Object:MyObject>#test - A method defined in a singleton object.
|
|
15
|
-
def full_name
|
|
16
|
-
decorated_class_name = case self.klass_flags
|
|
17
|
-
when 0x2
|
|
18
|
-
"<Class::#{klass_name}>"
|
|
19
|
-
when 0x4
|
|
20
|
-
"<Module::#{klass_name}>"
|
|
21
|
-
when 0x8
|
|
22
|
-
"<Object::#{klass_name}>"
|
|
23
|
-
else
|
|
24
|
-
klass_name
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
"#{decorated_class_name}##{method_name}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# The number of times this method was called
|
|
31
|
-
def called
|
|
32
|
-
self.measurement.called
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# The total time this method took - includes self time + wait time + child time
|
|
36
|
-
def total_time
|
|
37
|
-
self.measurement.total_time
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# The time this method took to execute
|
|
41
|
-
def self_time
|
|
42
|
-
self.measurement.self_time
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# The time this method waited for other fibers/threads to execute
|
|
46
|
-
def wait_time
|
|
47
|
-
self.measurement.wait_time
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# The time this method's children took to execute
|
|
51
|
-
def children_time
|
|
52
|
-
self.total_time - self.self_time - self.wait_time
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def eql?(other)
|
|
56
|
-
self.hash == other.hash
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def ==(other)
|
|
60
|
-
self.eql?(other)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def <=>(other)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
elsif self.
|
|
69
|
-
|
|
70
|
-
elsif self.total_time
|
|
71
|
-
1
|
|
72
|
-
elsif self.
|
|
73
|
-
1
|
|
74
|
-
elsif self.call_trees.min_depth
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
end
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module RubyProf
|
|
4
|
+
# The MethodInfo class is used to track information about each method that is profiled.
|
|
5
|
+
# You cannot create a MethodInfo object directly, they are generated while running a profile.
|
|
6
|
+
class MethodInfo
|
|
7
|
+
include Comparable
|
|
8
|
+
|
|
9
|
+
# Returns the full name of a class. The interpretation of method names is:
|
|
10
|
+
#
|
|
11
|
+
# * MyObject#test - An method defined in a class
|
|
12
|
+
# * <Class:MyObject>#test - A method defined in a singleton class.
|
|
13
|
+
# * <Module:MyObject>#test - A method defined in a singleton module.
|
|
14
|
+
# * <Object:MyObject>#test - A method defined in a singleton object.
|
|
15
|
+
def full_name
|
|
16
|
+
decorated_class_name = case self.klass_flags
|
|
17
|
+
when 0x2
|
|
18
|
+
"<Class::#{klass_name}>"
|
|
19
|
+
when 0x4
|
|
20
|
+
"<Module::#{klass_name}>"
|
|
21
|
+
when 0x8
|
|
22
|
+
"<Object::#{klass_name}>"
|
|
23
|
+
else
|
|
24
|
+
klass_name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
"#{decorated_class_name}##{method_name}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The number of times this method was called
|
|
31
|
+
def called
|
|
32
|
+
self.measurement.called
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The total time this method took - includes self time + wait time + child time
|
|
36
|
+
def total_time
|
|
37
|
+
self.measurement.total_time
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The time this method took to execute
|
|
41
|
+
def self_time
|
|
42
|
+
self.measurement.self_time
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The time this method waited for other fibers/threads to execute
|
|
46
|
+
def wait_time
|
|
47
|
+
self.measurement.wait_time
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The time this method's children took to execute
|
|
51
|
+
def children_time
|
|
52
|
+
self.total_time - self.self_time - self.wait_time
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def eql?(other)
|
|
56
|
+
self.hash == other.hash
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def ==(other)
|
|
60
|
+
self.eql?(other)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def <=>(other)
|
|
64
|
+
sort_delta = 0.0001
|
|
65
|
+
|
|
66
|
+
if other.nil?
|
|
67
|
+
-1
|
|
68
|
+
elsif self.full_name == other.full_name
|
|
69
|
+
0
|
|
70
|
+
elsif self.total_time < other.total_time && (self.total_time - other.total_time).abs > sort_delta
|
|
71
|
+
-1
|
|
72
|
+
elsif self.total_time > other.total_time && (self.total_time - other.total_time).abs > sort_delta
|
|
73
|
+
1
|
|
74
|
+
elsif self.call_trees.min_depth < other.call_trees.min_depth
|
|
75
|
+
1
|
|
76
|
+
elsif self.call_trees.min_depth > other.call_trees.min_depth
|
|
77
|
+
-1
|
|
78
|
+
else
|
|
79
|
+
self.full_name <=> other.full_name
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def to_s
|
|
84
|
+
"#{self.full_name} (c: #{self.called}, tt: #{self.total_time}, st: #{self.self_time}, wt: #{wait_time}, ct: #{self.children_time})"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|