ruby-prof 0.18.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 +7 -0
- data/CHANGES +500 -0
- data/LICENSE +25 -0
- data/README.rdoc +487 -0
- data/Rakefile +113 -0
- data/bin/ruby-prof +345 -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 +68 -0
- data/ext/ruby_prof/rp_call_info.c +425 -0
- data/ext/ruby_prof/rp_call_info.h +53 -0
- data/ext/ruby_prof/rp_measure.c +40 -0
- data/ext/ruby_prof/rp_measure.h +45 -0
- data/ext/ruby_prof/rp_measure_allocations.c +76 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +136 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +73 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +60 -0
- data/ext/ruby_prof/rp_measure_memory.c +77 -0
- data/ext/ruby_prof/rp_measure_process_time.c +71 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +45 -0
- data/ext/ruby_prof/rp_method.c +630 -0
- data/ext/ruby_prof/rp_method.h +75 -0
- data/ext/ruby_prof/rp_stack.c +173 -0
- data/ext/ruby_prof/rp_stack.h +63 -0
- data/ext/ruby_prof/rp_thread.c +277 -0
- data/ext/ruby_prof/rp_thread.h +27 -0
- data/ext/ruby_prof/ruby_prof.c +794 -0
- data/ext/ruby_prof/ruby_prof.h +60 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +141 -0
- data/lib/2.6.3/ruby_prof.so +0 -0
- data/lib/ruby-prof.rb +68 -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/call_info.rb +115 -0
- data/lib/ruby-prof/call_info_visitor.rb +40 -0
- data/lib/ruby-prof/compatibility.rb +179 -0
- data/lib/ruby-prof/method_info.rb +121 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +104 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +265 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +143 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/flat_printer.rb +70 -0
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +249 -0
- data/lib/ruby-prof/printers/graph_printer.rb +116 -0
- data/lib/ruby-prof/printers/multi_printer.rb +84 -0
- data/lib/ruby-prof/profile.rb +26 -0
- data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -0
- data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -0
- data/lib/ruby-prof/rack.rb +174 -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 +53 -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 +24 -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 +80 -0
- data/test/measure_allocations_test.rb +26 -0
- data/test/measure_cpu_time_test.rb +212 -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 +61 -0
- data/test/measure_wall_time_test.rb +255 -0
- data/test/method_elimination_test.rb +84 -0
- data/test/module_test.rb +45 -0
- data/test/multi_printer_test.rb +104 -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 +275 -0
- data/test/printing_recursive_graph_test.rb +127 -0
- data/test/rack_test.rb +157 -0
- data/test/recursive_test.rb +215 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +77 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +112 -0
- data/test/test_helper.rb +267 -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 +199 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require "mkmf"
|
2
|
+
|
3
|
+
if RUBY_ENGINE != "ruby"
|
4
|
+
STDERR.puts("\n\n***** This gem is MRI-specific. It does not support #{RUBY_ENGINE}. *****\n\n")
|
5
|
+
exit(1)
|
6
|
+
end
|
7
|
+
|
8
|
+
if RUBY_VERSION < "1.9.3"
|
9
|
+
STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.3 or higher. *****\n\n")
|
10
|
+
exit(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
# For the love of bitfields...
|
14
|
+
$CFLAGS += ' -std=c99'
|
15
|
+
|
16
|
+
# standard ruby methods
|
17
|
+
have_func("rb_gc_stat")
|
18
|
+
have_func("rb_gc_count")
|
19
|
+
have_func("rb_remove_event_hook_with_data")
|
20
|
+
|
21
|
+
# Alexander Dymo GC patch
|
22
|
+
have_func("rb_os_allocated_objects")
|
23
|
+
have_func("rb_gc_allocated_size")
|
24
|
+
|
25
|
+
# Stefan Kaes GC patches
|
26
|
+
have_func("rb_gc_collections")
|
27
|
+
have_func("rb_gc_time")
|
28
|
+
# for ruby 2.1
|
29
|
+
have_func("rb_gc_total_time")
|
30
|
+
have_func("rb_gc_total_mallocs")
|
31
|
+
have_func("rb_gc_total_malloced_bytes")
|
32
|
+
|
33
|
+
# Lloyd Hilaiel's heap info patch
|
34
|
+
have_func("rb_heap_total_mem")
|
35
|
+
have_func("rb_gc_heap_info")
|
36
|
+
|
37
|
+
def add_define(name, value = nil)
|
38
|
+
if value
|
39
|
+
$defs.push("-D#{name}=#{value}")
|
40
|
+
else
|
41
|
+
$defs.push("-D#{name}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def windows?
|
46
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
47
|
+
end
|
48
|
+
|
49
|
+
if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
|
50
|
+
$LDFLAGS += " -lrt" # for clock_gettime
|
51
|
+
end
|
52
|
+
add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
|
53
|
+
|
54
|
+
# for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 and later should work correctly)
|
55
|
+
if RUBY_VERSION > "1.9"
|
56
|
+
require 'set'
|
57
|
+
threads = Set.new
|
58
|
+
set_trace_func lambda { |*args| threads << Thread.current.object_id }
|
59
|
+
Thread.new{1}.join
|
60
|
+
set_trace_func nil
|
61
|
+
if threads.size < 2
|
62
|
+
# if we end up here, ruby does not automatically activate tracing in spawned threads
|
63
|
+
STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
|
64
|
+
exit(1)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
create_makefile("ruby_prof")
|
@@ -0,0 +1,425 @@
|
|
1
|
+
/* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
#include "ruby_prof.h"
|
5
|
+
|
6
|
+
#define INITIAL_CALL_INFOS_SIZE 2
|
7
|
+
|
8
|
+
VALUE cCallInfo;
|
9
|
+
|
10
|
+
|
11
|
+
// Forward declarations
|
12
|
+
st_table * call_info_table_create();
|
13
|
+
|
14
|
+
|
15
|
+
/* ======= prof_call_info_t ========*/
|
16
|
+
prof_call_info_t *
|
17
|
+
prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
|
18
|
+
{
|
19
|
+
prof_call_info_t *result = ALLOC(prof_call_info_t);
|
20
|
+
result->object = Qnil;
|
21
|
+
result->target = method;
|
22
|
+
result->parent = parent;
|
23
|
+
result->call_infos = call_info_table_create();
|
24
|
+
result->children = Qnil;
|
25
|
+
|
26
|
+
result->total_time = 0;
|
27
|
+
result->self_time = 0;
|
28
|
+
result->wait_time = 0;
|
29
|
+
|
30
|
+
result->called = 0;
|
31
|
+
|
32
|
+
result->recursive = 0;
|
33
|
+
result->depth = 0;
|
34
|
+
result->line = 0;
|
35
|
+
|
36
|
+
return result;
|
37
|
+
}
|
38
|
+
static void
|
39
|
+
prof_call_info_ruby_gc_free(prof_call_info_t *call_info)
|
40
|
+
{
|
41
|
+
/* Has this thread object been accessed by Ruby? If
|
42
|
+
yes clean it up so to avoid a segmentation fault. */
|
43
|
+
if (call_info->object != Qnil)
|
44
|
+
{
|
45
|
+
RDATA(call_info->object)->data = NULL;
|
46
|
+
RDATA(call_info->object)->dfree = NULL;
|
47
|
+
RDATA(call_info->object)->dmark = NULL;
|
48
|
+
}
|
49
|
+
call_info->object = Qnil;
|
50
|
+
}
|
51
|
+
|
52
|
+
static void
|
53
|
+
prof_call_info_free(prof_call_info_t *call_info)
|
54
|
+
{
|
55
|
+
prof_call_info_ruby_gc_free(call_info);
|
56
|
+
st_free_table(call_info->call_infos);
|
57
|
+
xfree(call_info);
|
58
|
+
}
|
59
|
+
|
60
|
+
static void
|
61
|
+
prof_call_info_mark(prof_call_info_t *call_info)
|
62
|
+
{
|
63
|
+
if (call_info->object)
|
64
|
+
rb_gc_mark(call_info->object);
|
65
|
+
|
66
|
+
if (call_info->children)
|
67
|
+
rb_gc_mark(call_info->children);
|
68
|
+
|
69
|
+
/* We don't mark the call info child table since that will be done
|
70
|
+
via the appropriate method */
|
71
|
+
}
|
72
|
+
|
73
|
+
VALUE
|
74
|
+
prof_call_info_wrap(prof_call_info_t *call_info)
|
75
|
+
{
|
76
|
+
if (call_info->object == Qnil)
|
77
|
+
{
|
78
|
+
call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
|
79
|
+
}
|
80
|
+
return call_info->object;
|
81
|
+
}
|
82
|
+
|
83
|
+
static prof_call_info_t *
|
84
|
+
prof_get_call_info(VALUE self)
|
85
|
+
{
|
86
|
+
/* Can't use Data_Get_Struct because that triggers the event hook
|
87
|
+
ending up in endless recursion. */
|
88
|
+
prof_call_info_t* result = DATA_PTR(self);
|
89
|
+
|
90
|
+
if (!result)
|
91
|
+
rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
|
92
|
+
|
93
|
+
return result;
|
94
|
+
}
|
95
|
+
|
96
|
+
/* ======= Call Info Table ========*/
|
97
|
+
st_table *
|
98
|
+
call_info_table_create()
|
99
|
+
{
|
100
|
+
return st_init_table(&type_method_hash);
|
101
|
+
}
|
102
|
+
|
103
|
+
size_t
|
104
|
+
call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
|
105
|
+
{
|
106
|
+
return st_insert(table, (st_data_t) key, (st_data_t) val);
|
107
|
+
}
|
108
|
+
|
109
|
+
prof_call_info_t *
|
110
|
+
call_info_table_lookup(st_table *table, const prof_method_key_t *key)
|
111
|
+
{
|
112
|
+
st_data_t val;
|
113
|
+
if (st_lookup(table, (st_data_t) key, &val))
|
114
|
+
{
|
115
|
+
return (prof_call_info_t *) val;
|
116
|
+
}
|
117
|
+
else
|
118
|
+
{
|
119
|
+
return NULL;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
/* ======= RubyProf::CallInfo ========*/
|
125
|
+
|
126
|
+
/* Document-class: RubyProf::CallInfo
|
127
|
+
RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
|
128
|
+
to keep track of which child methods were called and how long
|
129
|
+
they took to execute. */
|
130
|
+
|
131
|
+
|
132
|
+
/* call-seq:
|
133
|
+
called -> MethodInfo
|
134
|
+
|
135
|
+
Returns the target method. */
|
136
|
+
static VALUE
|
137
|
+
prof_call_info_target(VALUE self)
|
138
|
+
{
|
139
|
+
/* Target is a pointer to a method_info - so we have to be careful
|
140
|
+
about the GC. We will wrap the method_info but provide no
|
141
|
+
free method so the underlying object is not freed twice! */
|
142
|
+
|
143
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
144
|
+
return prof_method_wrap(result->target);
|
145
|
+
}
|
146
|
+
|
147
|
+
/* call-seq:
|
148
|
+
called -> int
|
149
|
+
|
150
|
+
Returns the total amount of times this method was called. */
|
151
|
+
static VALUE
|
152
|
+
prof_call_info_called(VALUE self)
|
153
|
+
{
|
154
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
155
|
+
return INT2NUM(result->called);
|
156
|
+
}
|
157
|
+
|
158
|
+
/* call-seq:
|
159
|
+
called=n -> n
|
160
|
+
|
161
|
+
Sets the call count to n. */
|
162
|
+
static VALUE
|
163
|
+
prof_call_info_set_called(VALUE self, VALUE called)
|
164
|
+
{
|
165
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
166
|
+
result->called = NUM2INT(called);
|
167
|
+
return called;
|
168
|
+
}
|
169
|
+
|
170
|
+
/* call-seq:
|
171
|
+
recursive? -> boolean
|
172
|
+
|
173
|
+
Returns the true if this call info is a recursive invocation */
|
174
|
+
static VALUE
|
175
|
+
prof_call_info_recursive(VALUE self)
|
176
|
+
{
|
177
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
178
|
+
return result->recursive ? Qtrue : Qfalse;
|
179
|
+
}
|
180
|
+
|
181
|
+
/* call-seq:
|
182
|
+
depth -> int
|
183
|
+
|
184
|
+
returns the depth of this call info in the call graph */
|
185
|
+
static VALUE
|
186
|
+
prof_call_info_depth(VALUE self)
|
187
|
+
{
|
188
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
189
|
+
return rb_int_new(result->depth);
|
190
|
+
}
|
191
|
+
|
192
|
+
/* call-seq:
|
193
|
+
line_no -> int
|
194
|
+
|
195
|
+
returns the line number of the method */
|
196
|
+
static VALUE
|
197
|
+
prof_call_info_line(VALUE self)
|
198
|
+
{
|
199
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
200
|
+
return rb_int_new(result->line);
|
201
|
+
}
|
202
|
+
|
203
|
+
/* call-seq:
|
204
|
+
total_time -> float
|
205
|
+
|
206
|
+
Returns the total amount of time spent in this method and its children. */
|
207
|
+
static VALUE
|
208
|
+
prof_call_info_total_time(VALUE self)
|
209
|
+
{
|
210
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
211
|
+
return rb_float_new(result->total_time);
|
212
|
+
}
|
213
|
+
|
214
|
+
/* call-seq:
|
215
|
+
add_total_time(call_info) -> nil
|
216
|
+
|
217
|
+
adds total time time from call_info to self. */
|
218
|
+
static VALUE
|
219
|
+
prof_call_info_add_total_time(VALUE self, VALUE other)
|
220
|
+
{
|
221
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
222
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
223
|
+
|
224
|
+
result->total_time += other_info->total_time;
|
225
|
+
return Qnil;
|
226
|
+
}
|
227
|
+
|
228
|
+
/* call-seq:
|
229
|
+
self_time -> float
|
230
|
+
|
231
|
+
Returns the total amount of time spent in this method. */
|
232
|
+
static VALUE
|
233
|
+
prof_call_info_self_time(VALUE self)
|
234
|
+
{
|
235
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
236
|
+
|
237
|
+
return rb_float_new(result->self_time);
|
238
|
+
}
|
239
|
+
|
240
|
+
/* call-seq:
|
241
|
+
add_self_time(call_info) -> nil
|
242
|
+
|
243
|
+
adds self time from call_info to self. */
|
244
|
+
static VALUE
|
245
|
+
prof_call_info_add_self_time(VALUE self, VALUE other)
|
246
|
+
{
|
247
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
248
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
249
|
+
|
250
|
+
result->self_time += other_info->self_time;
|
251
|
+
return Qnil;
|
252
|
+
}
|
253
|
+
|
254
|
+
/* call-seq:
|
255
|
+
wait_time -> float
|
256
|
+
|
257
|
+
Returns the total amount of time this method waited for other threads. */
|
258
|
+
static VALUE
|
259
|
+
prof_call_info_wait_time(VALUE self)
|
260
|
+
{
|
261
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
262
|
+
|
263
|
+
return rb_float_new(result->wait_time);
|
264
|
+
}
|
265
|
+
|
266
|
+
/* call-seq:
|
267
|
+
add_wait_time(call_info) -> nil
|
268
|
+
|
269
|
+
adds wait time from call_info to self. */
|
270
|
+
|
271
|
+
static VALUE
|
272
|
+
prof_call_info_add_wait_time(VALUE self, VALUE other)
|
273
|
+
{
|
274
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
275
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
276
|
+
|
277
|
+
result->wait_time += other_info->wait_time;
|
278
|
+
return Qnil;
|
279
|
+
}
|
280
|
+
|
281
|
+
/* call-seq:
|
282
|
+
parent -> call_info
|
283
|
+
|
284
|
+
Returns the call_infos parent call_info object (the method that called this method).*/
|
285
|
+
static VALUE
|
286
|
+
prof_call_info_parent(VALUE self)
|
287
|
+
{
|
288
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
289
|
+
if (result->parent)
|
290
|
+
return prof_call_info_wrap(result->parent);
|
291
|
+
else
|
292
|
+
return Qnil;
|
293
|
+
}
|
294
|
+
|
295
|
+
/* call-seq:
|
296
|
+
parent=new_parent -> new_parent
|
297
|
+
|
298
|
+
Changes the parent of self to new_parent and returns it.*/
|
299
|
+
static VALUE
|
300
|
+
prof_call_info_set_parent(VALUE self, VALUE new_parent)
|
301
|
+
{
|
302
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
303
|
+
if (new_parent == Qnil)
|
304
|
+
result->parent = NULL;
|
305
|
+
else
|
306
|
+
result->parent = prof_get_call_info(new_parent);
|
307
|
+
return prof_call_info_parent(self);
|
308
|
+
}
|
309
|
+
|
310
|
+
static int
|
311
|
+
prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
|
312
|
+
{
|
313
|
+
prof_call_info_t *call_info = (prof_call_info_t *) value;
|
314
|
+
VALUE arr = (VALUE) result;
|
315
|
+
rb_ary_push(arr, prof_call_info_wrap(call_info));
|
316
|
+
return ST_CONTINUE;
|
317
|
+
}
|
318
|
+
|
319
|
+
/* call-seq:
|
320
|
+
children -> hash
|
321
|
+
|
322
|
+
Returns an array of call info objects of methods that this method
|
323
|
+
called (ie, children).*/
|
324
|
+
static VALUE
|
325
|
+
prof_call_info_children(VALUE self)
|
326
|
+
{
|
327
|
+
prof_call_info_t *call_info = prof_get_call_info(self);
|
328
|
+
if (call_info->children == Qnil)
|
329
|
+
{
|
330
|
+
call_info->children = rb_ary_new();
|
331
|
+
st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
|
332
|
+
}
|
333
|
+
return call_info->children;
|
334
|
+
}
|
335
|
+
|
336
|
+
/* ======= Call Infos ========*/
|
337
|
+
prof_call_infos_t*
|
338
|
+
prof_call_infos_create()
|
339
|
+
{
|
340
|
+
prof_call_infos_t *result = ALLOC(prof_call_infos_t);
|
341
|
+
result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
|
342
|
+
result->end = result->start + INITIAL_CALL_INFOS_SIZE;
|
343
|
+
result->ptr = result->start;
|
344
|
+
result->object = Qnil;
|
345
|
+
return result;
|
346
|
+
}
|
347
|
+
|
348
|
+
void
|
349
|
+
prof_call_infos_mark(prof_call_infos_t *call_infos)
|
350
|
+
{
|
351
|
+
prof_call_info_t **call_info;
|
352
|
+
|
353
|
+
if (call_infos->object)
|
354
|
+
rb_gc_mark(call_infos->object);
|
355
|
+
|
356
|
+
for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
|
357
|
+
{
|
358
|
+
prof_call_info_mark(*call_info);
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
void
|
363
|
+
prof_call_infos_free(prof_call_infos_t *call_infos)
|
364
|
+
{
|
365
|
+
prof_call_info_t **call_info;
|
366
|
+
|
367
|
+
for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
|
368
|
+
{
|
369
|
+
prof_call_info_free(*call_info);
|
370
|
+
}
|
371
|
+
}
|
372
|
+
|
373
|
+
void
|
374
|
+
prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
|
375
|
+
{
|
376
|
+
if (call_infos->ptr == call_infos->end)
|
377
|
+
{
|
378
|
+
size_t len = call_infos->ptr - call_infos->start;
|
379
|
+
size_t new_capacity = (call_infos->end - call_infos->start) * 2;
|
380
|
+
REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
|
381
|
+
call_infos->ptr = call_infos->start + len;
|
382
|
+
call_infos->end = call_infos->start + new_capacity;
|
383
|
+
}
|
384
|
+
*call_infos->ptr = call_info;
|
385
|
+
call_infos->ptr++;
|
386
|
+
}
|
387
|
+
|
388
|
+
VALUE
|
389
|
+
prof_call_infos_wrap(prof_call_infos_t *call_infos)
|
390
|
+
{
|
391
|
+
if (call_infos->object == Qnil)
|
392
|
+
{
|
393
|
+
prof_call_info_t **i;
|
394
|
+
call_infos->object = rb_ary_new();
|
395
|
+
for(i=call_infos->start; i<call_infos->ptr; i++)
|
396
|
+
{
|
397
|
+
VALUE call_info = prof_call_info_wrap(*i);
|
398
|
+
rb_ary_push(call_infos->object, call_info);
|
399
|
+
}
|
400
|
+
}
|
401
|
+
return call_infos->object;
|
402
|
+
}
|
403
|
+
|
404
|
+
void rp_init_call_info()
|
405
|
+
{
|
406
|
+
/* CallInfo */
|
407
|
+
cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
|
408
|
+
rb_undef_method(CLASS_OF(cCallInfo), "new");
|
409
|
+
rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
|
410
|
+
rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
|
411
|
+
rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
|
412
|
+
rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
|
413
|
+
rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
|
414
|
+
rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
|
415
|
+
rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
|
416
|
+
rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
|
417
|
+
rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
|
418
|
+
rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
|
419
|
+
rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
|
420
|
+
rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
|
421
|
+
|
422
|
+
rb_define_method(cCallInfo, "recursive?", prof_call_info_recursive, 0);
|
423
|
+
rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
|
424
|
+
rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
|
425
|
+
}
|