ruby-prof 1.4.3 → 1.6.3
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 +59 -9
- data/{README.rdoc → README.md} +2 -2
- data/Rakefile +4 -4
- data/bin/ruby-prof +100 -87
- data/ext/ruby_prof/rp_allocation.c +140 -85
- data/ext/ruby_prof/rp_allocation.h +8 -6
- data/ext/ruby_prof/rp_call_tree.c +502 -369
- data/ext/ruby_prof/rp_call_tree.h +47 -43
- data/ext/ruby_prof/rp_call_trees.c +16 -8
- data/ext/ruby_prof/rp_measure_allocations.c +10 -13
- data/ext/ruby_prof/rp_measure_memory.c +8 -4
- data/ext/ruby_prof/rp_measure_process_time.c +7 -6
- data/ext/ruby_prof/rp_measurement.c +147 -20
- data/ext/ruby_prof/rp_measurement.h +4 -1
- data/ext/ruby_prof/rp_method.c +142 -83
- data/ext/ruby_prof/rp_method.h +63 -62
- data/ext/ruby_prof/rp_profile.c +933 -900
- data/ext/ruby_prof/rp_profile.h +1 -0
- data/ext/ruby_prof/rp_thread.c +433 -362
- data/ext/ruby_prof/rp_thread.h +39 -39
- data/ext/ruby_prof/ruby_prof.c +0 -2
- data/ext/ruby_prof/ruby_prof.h +8 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -8
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
- data/lib/ruby-prof/compatibility.rb +14 -0
- data/lib/ruby-prof/method_info.rb +8 -1
- data/lib/ruby-prof/printers/abstract_printer.rb +2 -1
- data/lib/ruby-prof/printers/call_tree_printer.rb +4 -10
- data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
- data/lib/ruby-prof/printers/multi_printer.rb +17 -17
- data/lib/ruby-prof/profile.rb +70 -37
- data/lib/ruby-prof/rack.rb +31 -21
- data/lib/ruby-prof/version.rb +1 -1
- data/lib/ruby-prof.rb +1 -1
- data/ruby-prof.gemspec +2 -3
- data/test/abstract_printer_test.rb +1 -0
- data/test/alias_test.rb +97 -106
- data/test/call_tree_builder.rb +126 -0
- data/test/call_tree_test.rb +94 -0
- data/test/call_tree_visitor_test.rb +1 -6
- data/test/call_trees_test.rb +6 -6
- data/test/{basic_test.rb → compatibility_test.rb} +8 -2
- data/test/duplicate_names_test.rb +5 -5
- data/test/dynamic_method_test.rb +24 -15
- data/test/enumerable_test.rb +1 -1
- data/test/exceptions_test.rb +2 -2
- data/test/exclude_methods_test.rb +3 -8
- data/test/exclude_threads_test.rb +4 -9
- data/test/fiber_test.rb +74 -8
- data/test/gc_test.rb +11 -9
- data/test/inverse_call_tree_test.rb +33 -34
- data/test/line_number_test.rb +37 -61
- data/test/marshal_test.rb +16 -3
- data/test/measure_allocations.rb +1 -5
- data/test/measure_allocations_test.rb +642 -357
- data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +180 -616
- data/test/measure_process_time_test.rb +1566 -741
- data/test/measure_wall_time_test.rb +179 -193
- data/test/measurement_test.rb +82 -0
- data/test/merge_test.rb +146 -0
- data/test/method_info_test.rb +95 -0
- data/test/multi_printer_test.rb +0 -5
- data/test/no_method_class_test.rb +1 -1
- data/test/pause_resume_test.rb +12 -16
- data/test/printer_call_stack_test.rb +2 -2
- data/test/printer_call_tree_test.rb +4 -4
- data/test/printer_flat_test.rb +1 -1
- data/test/printer_graph_html_test.rb +2 -2
- data/test/printer_graph_test.rb +2 -2
- data/test/printers_test.rb +14 -20
- data/test/printing_recursive_graph_test.rb +2 -2
- data/test/profile_test.rb +85 -0
- data/test/recursive_test.rb +374 -155
- data/test/scheduler.rb +363 -0
- data/test/singleton_test.rb +1 -1
- data/test/stack_printer_test.rb +5 -8
- data/test/start_stop_test.rb +11 -14
- data/test/test_helper.rb +11 -8
- data/test/thread_test.rb +106 -15
- data/test/unique_call_path_test.rb +28 -12
- data/test/yarv_test.rb +11 -7
- metadata +17 -29
- data/ext/ruby_prof/rp_aggregate_call_tree.c +0 -59
- data/ext/ruby_prof/rp_aggregate_call_tree.h +0 -13
- data/test/measure_allocations_trace_test.rb +0 -375
- data/test/temp.rb +0 -20
@@ -2,32 +2,11 @@
|
|
2
2
|
Please see the LICENSE file for copyright and distribution information */
|
3
3
|
|
4
4
|
#include "rp_allocation.h"
|
5
|
+
#include "rp_method.h"
|
5
6
|
|
6
7
|
VALUE cRpAllocation;
|
7
8
|
|
8
|
-
|
9
|
-
{
|
10
|
-
prof_allocation_t* result = NULL;
|
11
|
-
st_data_t value;
|
12
|
-
if (rb_st_lookup(table, key, &value))
|
13
|
-
{
|
14
|
-
result = (prof_allocation_t*)value;
|
15
|
-
}
|
16
|
-
|
17
|
-
return result;
|
18
|
-
}
|
19
|
-
|
20
|
-
void allocations_table_insert(st_table* table, st_data_t key, prof_allocation_t* allocation)
|
21
|
-
{
|
22
|
-
rb_st_insert(table, (st_data_t)key, (st_data_t)allocation);
|
23
|
-
}
|
24
|
-
|
25
|
-
st_data_t allocations_key(VALUE klass, int source_line)
|
26
|
-
{
|
27
|
-
return (klass << 4) + source_line;
|
28
|
-
}
|
29
|
-
|
30
|
-
/* ====== prof_allocation_t ====== */
|
9
|
+
// ------ prof_allocation_t ------
|
31
10
|
prof_allocation_t* prof_allocation_create(void)
|
32
11
|
{
|
33
12
|
prof_allocation_t* result = ALLOC(prof_allocation_t);
|
@@ -43,48 +22,17 @@ prof_allocation_t* prof_allocation_create(void)
|
|
43
22
|
return result;
|
44
23
|
}
|
45
24
|
|
46
|
-
prof_allocation_t*
|
25
|
+
prof_allocation_t* prof_allocation_get(VALUE self)
|
47
26
|
{
|
48
27
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
49
28
|
ending up in endless recursion. */
|
50
29
|
prof_allocation_t* result = RTYPEDDATA_DATA(self);
|
51
|
-
|
52
30
|
if (!result)
|
53
31
|
rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
|
54
32
|
|
55
33
|
return result;
|
56
34
|
}
|
57
35
|
|
58
|
-
prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
59
|
-
{
|
60
|
-
VALUE object = rb_tracearg_object(trace_arg);
|
61
|
-
if (BUILTIN_TYPE(object) == T_IMEMO)
|
62
|
-
return NULL;
|
63
|
-
|
64
|
-
VALUE klass = rb_obj_class(object);
|
65
|
-
|
66
|
-
int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
|
67
|
-
st_data_t key = allocations_key(klass, source_line);
|
68
|
-
|
69
|
-
prof_allocation_t* allocation = allocations_table_lookup(method->allocations_table, key);
|
70
|
-
if (!allocation)
|
71
|
-
{
|
72
|
-
allocation = prof_allocation_create();
|
73
|
-
allocation->source_line = source_line;
|
74
|
-
allocation->source_file = rb_tracearg_path(trace_arg);
|
75
|
-
allocation->klass_flags = 0;
|
76
|
-
allocation->klass = resolve_klass(klass, &allocation->klass_flags);
|
77
|
-
|
78
|
-
allocation->key = key;
|
79
|
-
allocations_table_insert(method->allocations_table, key, allocation);
|
80
|
-
}
|
81
|
-
|
82
|
-
allocation->count++;
|
83
|
-
allocation->memory += rb_obj_memsize_of(object);
|
84
|
-
|
85
|
-
return allocation;
|
86
|
-
}
|
87
|
-
|
88
36
|
static void prof_allocation_ruby_gc_free(void* data)
|
89
37
|
{
|
90
38
|
if (data)
|
@@ -118,30 +66,39 @@ void prof_allocation_mark(void* data)
|
|
118
66
|
|
119
67
|
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
120
68
|
if (allocation->object != Qnil)
|
121
|
-
|
69
|
+
rb_gc_mark_movable(allocation->object);
|
122
70
|
|
123
71
|
if (allocation->klass != Qnil)
|
124
|
-
|
72
|
+
rb_gc_mark_movable(allocation->klass);
|
125
73
|
|
126
74
|
if (allocation->klass_name != Qnil)
|
127
|
-
|
75
|
+
rb_gc_mark_movable(allocation->klass_name);
|
128
76
|
|
129
77
|
if (allocation->source_file != Qnil)
|
130
78
|
rb_gc_mark(allocation->source_file);
|
131
79
|
}
|
132
80
|
|
133
|
-
|
81
|
+
void prof_allocation_compact(void* data)
|
134
82
|
{
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
83
|
+
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
84
|
+
allocation->object = rb_gc_location(allocation->object);
|
85
|
+
allocation->klass = rb_gc_location(allocation->klass);
|
86
|
+
allocation->klass_name = rb_gc_location(allocation->klass_name);
|
87
|
+
}
|
88
|
+
|
89
|
+
static const rb_data_type_t allocation_type =
|
90
|
+
{
|
91
|
+
.wrap_struct_name = "Allocation",
|
92
|
+
.function =
|
93
|
+
{
|
94
|
+
.dmark = prof_allocation_mark,
|
95
|
+
.dfree = prof_allocation_ruby_gc_free,
|
96
|
+
.dsize = prof_allocation_size,
|
97
|
+
.dcompact = prof_allocation_compact
|
98
|
+
},
|
99
|
+
.data = NULL,
|
100
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
101
|
+
};
|
145
102
|
|
146
103
|
VALUE prof_allocation_wrap(prof_allocation_t* allocation)
|
147
104
|
{
|
@@ -152,24 +109,122 @@ VALUE prof_allocation_wrap(prof_allocation_t* allocation)
|
|
152
109
|
return allocation->object;
|
153
110
|
}
|
154
111
|
|
155
|
-
|
112
|
+
/* ====== Allocation Table ====== */
|
113
|
+
st_table* prof_allocations_create()
|
156
114
|
{
|
157
|
-
|
158
|
-
allocation->object = prof_allocation_wrap(allocation);
|
159
|
-
return allocation->object;
|
115
|
+
return rb_st_init_numtable();
|
160
116
|
}
|
161
117
|
|
162
|
-
|
118
|
+
static int allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
|
163
119
|
{
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
120
|
+
prof_allocation_free((prof_allocation_t*)value);
|
121
|
+
return ST_CONTINUE;
|
122
|
+
}
|
123
|
+
|
124
|
+
st_data_t allocations_key(VALUE klass, int source_line)
|
125
|
+
{
|
126
|
+
return (klass << 4) + source_line;
|
127
|
+
}
|
128
|
+
|
129
|
+
static int prof_allocations_collect(st_data_t key, st_data_t value, st_data_t result)
|
130
|
+
{
|
131
|
+
prof_allocation_t* allocation = (prof_allocation_t*)value;
|
132
|
+
VALUE arr = (VALUE)result;
|
133
|
+
rb_ary_push(arr, prof_allocation_wrap(allocation));
|
134
|
+
return ST_CONTINUE;
|
135
|
+
}
|
136
|
+
|
137
|
+
static int prof_allocations_mark_each(st_data_t key, st_data_t value, st_data_t data)
|
138
|
+
{
|
139
|
+
prof_allocation_t* allocation = (prof_allocation_t*)value;
|
140
|
+
prof_allocation_mark(allocation);
|
141
|
+
return ST_CONTINUE;
|
142
|
+
}
|
143
|
+
|
144
|
+
void prof_allocations_mark(st_table* allocations_table)
|
145
|
+
{
|
146
|
+
rb_st_foreach(allocations_table, prof_allocations_mark_each, 0);
|
147
|
+
}
|
148
|
+
|
149
|
+
void prof_allocations_free(st_table* table)
|
150
|
+
{
|
151
|
+
rb_st_foreach(table, allocations_table_free_iterator, 0);
|
152
|
+
rb_st_free_table(table);
|
153
|
+
}
|
154
|
+
|
155
|
+
prof_allocation_t* allocations_table_lookup(st_table* table, st_data_t key)
|
156
|
+
{
|
157
|
+
prof_allocation_t* result = NULL;
|
158
|
+
st_data_t value;
|
159
|
+
if (rb_st_lookup(table, key, &value))
|
160
|
+
{
|
161
|
+
result = (prof_allocation_t*)value;
|
162
|
+
}
|
169
163
|
|
170
164
|
return result;
|
171
165
|
}
|
172
166
|
|
167
|
+
void allocations_table_insert(st_table* table, st_data_t key, prof_allocation_t* allocation)
|
168
|
+
{
|
169
|
+
rb_st_insert(table, (st_data_t)key, (st_data_t)allocation);
|
170
|
+
}
|
171
|
+
|
172
|
+
prof_allocation_t* prof_allocate_increment(st_table* allocations_table, rb_trace_arg_t* trace_arg)
|
173
|
+
{
|
174
|
+
VALUE object = rb_tracearg_object(trace_arg);
|
175
|
+
if (BUILTIN_TYPE(object) == T_IMEMO)
|
176
|
+
return NULL;
|
177
|
+
|
178
|
+
VALUE klass = rb_obj_class(object);
|
179
|
+
|
180
|
+
int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
|
181
|
+
st_data_t key = allocations_key(klass, source_line);
|
182
|
+
|
183
|
+
prof_allocation_t* allocation = allocations_table_lookup(allocations_table, key);
|
184
|
+
if (!allocation)
|
185
|
+
{
|
186
|
+
allocation = prof_allocation_create();
|
187
|
+
allocation->source_line = source_line;
|
188
|
+
allocation->source_file = rb_tracearg_path(trace_arg);
|
189
|
+
allocation->klass_flags = 0;
|
190
|
+
allocation->klass = resolve_klass(klass, &allocation->klass_flags);
|
191
|
+
|
192
|
+
allocation->key = key;
|
193
|
+
allocations_table_insert(allocations_table, key, allocation);
|
194
|
+
}
|
195
|
+
|
196
|
+
allocation->count++;
|
197
|
+
allocation->memory += rb_obj_memsize_of(object);
|
198
|
+
|
199
|
+
return allocation;
|
200
|
+
}
|
201
|
+
|
202
|
+
// Returns an array of allocations
|
203
|
+
VALUE prof_allocations_wrap(st_table* allocations_table)
|
204
|
+
{
|
205
|
+
VALUE result = rb_ary_new();
|
206
|
+
rb_st_foreach(allocations_table, prof_allocations_collect, result);
|
207
|
+
return result;
|
208
|
+
}
|
209
|
+
|
210
|
+
void prof_allocations_unwrap(st_table* allocations_table, VALUE allocations)
|
211
|
+
{
|
212
|
+
for (int i = 0; i < rb_array_len(allocations); i++)
|
213
|
+
{
|
214
|
+
VALUE allocation = rb_ary_entry(allocations, i);
|
215
|
+
prof_allocation_t* allocation_data = prof_allocation_get(allocation);
|
216
|
+
rb_st_insert(allocations_table, allocation_data->key, (st_data_t)allocation_data);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
/* ====== prof_allocation_t ====== */
|
221
|
+
static VALUE prof_allocation_allocate(VALUE klass)
|
222
|
+
{
|
223
|
+
prof_allocation_t* allocation = prof_allocation_create();
|
224
|
+
allocation->object = prof_allocation_wrap(allocation);
|
225
|
+
return allocation->object;
|
226
|
+
}
|
227
|
+
|
173
228
|
/* call-seq:
|
174
229
|
klass -> Class
|
175
230
|
|
@@ -238,17 +293,17 @@ static VALUE prof_allocation_memory(VALUE self)
|
|
238
293
|
/* :nodoc: */
|
239
294
|
static VALUE prof_allocation_dump(VALUE self)
|
240
295
|
{
|
241
|
-
prof_allocation_t* allocation =
|
296
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
242
297
|
|
243
298
|
VALUE result = rb_hash_new();
|
244
299
|
|
245
|
-
rb_hash_aset(result, ID2SYM(rb_intern("key")),
|
300
|
+
rb_hash_aset(result, ID2SYM(rb_intern("key")), ULL2NUM(allocation->key));
|
246
301
|
rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_allocation_klass_name(self));
|
247
302
|
rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(allocation->klass_flags));
|
248
303
|
rb_hash_aset(result, ID2SYM(rb_intern("source_file")), allocation->source_file);
|
249
304
|
rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(allocation->source_line));
|
250
305
|
rb_hash_aset(result, ID2SYM(rb_intern("count")), INT2FIX(allocation->count));
|
251
|
-
rb_hash_aset(result, ID2SYM(rb_intern("memory")),
|
306
|
+
rb_hash_aset(result, ID2SYM(rb_intern("memory")), ULL2NUM(allocation->memory));
|
252
307
|
|
253
308
|
return result;
|
254
309
|
}
|
@@ -256,16 +311,16 @@ static VALUE prof_allocation_dump(VALUE self)
|
|
256
311
|
/* :nodoc: */
|
257
312
|
static VALUE prof_allocation_load(VALUE self, VALUE data)
|
258
313
|
{
|
259
|
-
prof_allocation_t* allocation =
|
314
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
260
315
|
allocation->object = self;
|
261
316
|
|
262
|
-
allocation->key =
|
317
|
+
allocation->key = RB_NUM2ULL(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
|
263
318
|
allocation->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
|
264
319
|
allocation->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
|
265
320
|
allocation->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
|
266
321
|
allocation->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
|
267
322
|
allocation->count = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("count"))));
|
268
|
-
allocation->memory =
|
323
|
+
allocation->memory = NUM2ULONG(rb_hash_aref(data, ID2SYM(rb_intern("memory"))));
|
269
324
|
|
270
325
|
return data;
|
271
326
|
}
|
@@ -5,7 +5,6 @@
|
|
5
5
|
#define _RP_ALLOCATION_
|
6
6
|
|
7
7
|
#include "ruby_prof.h"
|
8
|
-
#include "rp_method.h"
|
9
8
|
|
10
9
|
typedef struct prof_allocation_t
|
11
10
|
{
|
@@ -20,12 +19,15 @@ typedef struct prof_allocation_t
|
|
20
19
|
VALUE object; /* Cache to wrapped object */
|
21
20
|
} prof_allocation_t;
|
22
21
|
|
22
|
+
// Allocation (prof_allocation_t*)
|
23
23
|
void rp_init_allocation(void);
|
24
|
-
|
25
|
-
void prof_allocation_mark(void* data);
|
26
|
-
VALUE prof_allocation_wrap(prof_allocation_t* allocation);
|
27
|
-
prof_allocation_t* prof_allocation_get(VALUE self);
|
28
|
-
prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg);
|
24
|
+
prof_allocation_t* prof_allocate_increment(st_table* allocations_table, rb_trace_arg_t* trace_arg);
|
29
25
|
|
26
|
+
// Allocations (st_table*)
|
27
|
+
st_table* prof_allocations_create(void);
|
28
|
+
VALUE prof_allocations_wrap(st_table* allocations_table);
|
29
|
+
void prof_allocations_unwrap(st_table* allocations_table, VALUE allocations);
|
30
|
+
void prof_allocations_mark(st_table* allocations_table);
|
31
|
+
void prof_allocations_free(st_table* table);
|
30
32
|
|
31
33
|
#endif //_RP_ALLOCATION_
|