allocation_tracer 0.0.2 → 0.0.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76c7a52b186ed762bc19644997b2d57e66fbb431
|
4
|
+
data.tar.gz: 2b945274f4255f0c06374354a66bde0d0f3bcf13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 518dcab890b67dab01d987ef98a277c7364521777c5c9edef0057543cc34719a369ceec93d81c020dd96700894c0da3aeb582d2b19720e7b3fc5899f26543e18
|
7
|
+
data.tar.gz: 6b7792f6f02388a69d4fb21a92b2cb9c94605125db49c14af5821fd5700c5be99b2b892c646300030130b25fad4b320a33bb65f100d50c7fe8ac92e9fee4cd86
|
@@ -8,6 +8,8 @@
|
|
8
8
|
#include "ruby/ruby.h"
|
9
9
|
#include "ruby/debug.h"
|
10
10
|
|
11
|
+
size_t rb_obj_memsize_of(VALUE obj); /* in gc.c */
|
12
|
+
|
11
13
|
static VALUE rb_mAllocationTracer;
|
12
14
|
|
13
15
|
struct allocation_info {
|
@@ -16,6 +18,7 @@ struct allocation_info {
|
|
16
18
|
VALUE flags;
|
17
19
|
VALUE klass;
|
18
20
|
size_t generation;
|
21
|
+
size_t memsize;
|
19
22
|
|
20
23
|
/* allocation info */
|
21
24
|
const char *path;
|
@@ -33,6 +36,7 @@ struct allocation_info {
|
|
33
36
|
#define VAL_TOTAL_AGE (1<<2)
|
34
37
|
#define VAL_MAX_AGE (1<<3)
|
35
38
|
#define VAL_MIN_AGE (1<<4)
|
39
|
+
#define VAL_MEMSIZE (1<<5)
|
36
40
|
|
37
41
|
struct traceobj_arg {
|
38
42
|
int running;
|
@@ -133,7 +137,7 @@ get_traceobj_arg(void)
|
|
133
137
|
tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1);
|
134
138
|
tmp_trace_arg->running = 0;
|
135
139
|
tmp_trace_arg->keys = 0;
|
136
|
-
tmp_trace_arg->vals = VAL_COUNT | VAL_TOTAL_AGE | VAL_MAX_AGE | VAL_MIN_AGE;
|
140
|
+
tmp_trace_arg->vals = VAL_COUNT | VAL_TOTAL_AGE | VAL_MAX_AGE | VAL_MIN_AGE | VAL_MEMSIZE;
|
137
141
|
tmp_trace_arg->aggregate_table = st_init_table(&memcmp_hash_type);
|
138
142
|
tmp_trace_arg->object_table = st_init_numtable();
|
139
143
|
tmp_trace_arg->str_table = st_init_strtable();
|
@@ -199,6 +203,7 @@ newobj_i(VALUE tpval, void *data)
|
|
199
203
|
VALUE obj = rb_tracearg_object(tparg);
|
200
204
|
VALUE path = rb_tracearg_path(tparg);
|
201
205
|
VALUE line = rb_tracearg_lineno(tparg);
|
206
|
+
VALUE klass = RBASIC_CLASS(obj);
|
202
207
|
const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : NULL;
|
203
208
|
|
204
209
|
if (st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
|
@@ -215,7 +220,7 @@ newobj_i(VALUE tpval, void *data)
|
|
215
220
|
info->next = NULL;
|
216
221
|
info->living = 1;
|
217
222
|
info->flags = RBASIC(obj)->flags;
|
218
|
-
info->klass = rb_class_real(
|
223
|
+
info->klass = RTEST(klass) ? rb_class_real(klass) : Qnil;
|
219
224
|
info->generation = rb_gc_count();
|
220
225
|
|
221
226
|
info->path = path_cstr;
|
@@ -240,8 +245,8 @@ aggregator_i(void *data)
|
|
240
245
|
struct allocation_info *next_info = info->next;
|
241
246
|
st_data_t key, val;
|
242
247
|
struct memcmp_key_data key_data;
|
243
|
-
|
244
|
-
|
248
|
+
size_t *val_buff;
|
249
|
+
size_t age = (int)(gc_count - info->generation);
|
245
250
|
int i;
|
246
251
|
|
247
252
|
i = 0;
|
@@ -270,22 +275,24 @@ aggregator_i(void *data)
|
|
270
275
|
key = (st_data_t)key_buff;
|
271
276
|
|
272
277
|
/* count, total age, max age, min age */
|
273
|
-
val_buff = ALLOC_N(
|
278
|
+
val_buff = ALLOC_N(size_t, 5);
|
274
279
|
val_buff[0] = val_buff[1] = 0;
|
275
280
|
val_buff[2] = val_buff[3] = age;
|
281
|
+
val_buff[4] = 0;
|
276
282
|
|
277
283
|
if (arg->keys & KEY_PATH) keep_unique_str(arg->str_table, info->path);
|
278
284
|
|
279
285
|
st_insert(arg->aggregate_table, (st_data_t)key_buff, (st_data_t)val_buff);
|
280
286
|
}
|
281
287
|
else {
|
282
|
-
val_buff = (
|
288
|
+
val_buff = (size_t *)val;
|
283
289
|
}
|
284
290
|
|
285
291
|
val_buff[0] += 1;
|
286
292
|
val_buff[1] += age;
|
287
293
|
if (val_buff[2] > age) val_buff[2] = age;
|
288
294
|
if (val_buff[3] < age) val_buff[3] = age;
|
295
|
+
val_buff[4] += info->memsize;
|
289
296
|
|
290
297
|
free_allocation_info(arg, info);
|
291
298
|
info = next_info;
|
@@ -293,8 +300,9 @@ aggregator_i(void *data)
|
|
293
300
|
}
|
294
301
|
|
295
302
|
static void
|
296
|
-
move_to_freed_list(struct traceobj_arg *arg, struct allocation_info *info)
|
303
|
+
move_to_freed_list(struct traceobj_arg *arg, VALUE obj, struct allocation_info *info)
|
297
304
|
{
|
305
|
+
info->memsize = rb_obj_memsize_of(obj);
|
298
306
|
info->next = arg->freed_allocation_info;
|
299
307
|
arg->freed_allocation_info = info;
|
300
308
|
}
|
@@ -312,7 +320,7 @@ freeobj_i(VALUE tpval, void *data)
|
|
312
320
|
}
|
313
321
|
|
314
322
|
if (st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
|
315
|
-
move_to_freed_list(arg, info);
|
323
|
+
move_to_freed_list(arg, obj, info);
|
316
324
|
st_delete(arg->object_table, (st_data_t *)&obj, (st_data_t *)&info);
|
317
325
|
}
|
318
326
|
}
|
@@ -382,9 +390,9 @@ aggregate_result_i(st_data_t key, st_data_t val, void *data)
|
|
382
390
|
struct traceobj_arg *arg = aar->arg;
|
383
391
|
VALUE result = aar->result;
|
384
392
|
|
385
|
-
|
393
|
+
size_t *val_buff = (size_t *)val;
|
386
394
|
struct memcmp_key_data *key_buff = (struct memcmp_key_data *)key;
|
387
|
-
VALUE v = rb_ary_new3(
|
395
|
+
VALUE v = rb_ary_new3(5, INT2FIX(val_buff[0]), INT2FIX(val_buff[1]), INT2FIX(val_buff[2]), INT2FIX(val_buff[3]), INT2FIX(val_buff[4]));
|
388
396
|
VALUE k = rb_ary_new();
|
389
397
|
int i = 0;
|
390
398
|
static VALUE type_symbols[T_MASK] = {0};
|
@@ -415,7 +423,7 @@ aggregate_result_i(st_data_t key, st_data_t val, void *data)
|
|
415
423
|
}
|
416
424
|
if (arg->keys & KEY_CLASS) {
|
417
425
|
VALUE klass = key_buff->data[i++];
|
418
|
-
if (BUILTIN_TYPE(klass) == T_CLASS) {
|
426
|
+
if (RTEST(klass) && BUILTIN_TYPE(klass) == T_CLASS) {
|
419
427
|
klass = rb_class_real(klass);
|
420
428
|
rb_ary_push(k, klass);
|
421
429
|
/* TODO: actually, it is dangerous code because klass can be sweeped */
|
@@ -436,7 +444,7 @@ aggregate_rest_object_i(st_data_t key, st_data_t val, void *data)
|
|
436
444
|
{
|
437
445
|
struct traceobj_arg *arg = (struct traceobj_arg *)data;
|
438
446
|
struct allocation_info *info = (struct allocation_info *)val;
|
439
|
-
move_to_freed_list(arg, info);
|
447
|
+
move_to_freed_list(arg, (VALUE)key, info);
|
440
448
|
return ST_CONTINUE;
|
441
449
|
}
|
442
450
|
|
@@ -547,6 +555,7 @@ allocation_tracer_header(VALUE self)
|
|
547
555
|
if (arg->vals & VAL_TOTAL_AGE) rb_ary_push(ary, ID2SYM(rb_intern("total_age")));
|
548
556
|
if (arg->vals & VAL_MAX_AGE) rb_ary_push(ary, ID2SYM(rb_intern("max_age")));
|
549
557
|
if (arg->vals & VAL_MIN_AGE) rb_ary_push(ary, ID2SYM(rb_intern("min_age")));
|
558
|
+
if (arg->vals & VAL_MEMSIZE) rb_ary_push(ary, ID2SYM(rb_intern("memsize")));
|
550
559
|
|
551
560
|
return ary;
|
552
561
|
}
|
Binary file
|
@@ -11,7 +11,7 @@ describe ObjectSpace::AllocationTracer do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
expect(result.length).to be >= 1
|
14
|
-
expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0]
|
14
|
+
expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0, 0]
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should run twice' do
|
@@ -21,7 +21,17 @@ describe ObjectSpace::AllocationTracer do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
expect(result.length).to be >= 1
|
24
|
-
expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0]
|
24
|
+
expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0, 0]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should acquire allocated memsize' do
|
28
|
+
line = __LINE__ + 2
|
29
|
+
result = ObjectSpace::AllocationTracer.trace do
|
30
|
+
a = 'x' * 1234
|
31
|
+
end
|
32
|
+
|
33
|
+
expect(result.length).to be >= 1
|
34
|
+
expect(result[[__FILE__, line]][-1]).to be > 1234
|
25
35
|
end
|
26
36
|
|
27
37
|
describe 'with different setup' do
|
@@ -34,11 +44,11 @@ describe ObjectSpace::AllocationTracer do
|
|
34
44
|
end
|
35
45
|
|
36
46
|
expect(result.length).to be 5
|
37
|
-
expect(result[[__FILE__, line, :T_OBJECT]]).to eq [1, 0, 0, 0]
|
38
|
-
expect(result[[__FILE__, line, :T_ARRAY]]).to eq [1, 0, 0, 0]
|
39
|
-
expect(result[[__FILE__, line + 1, :T_HASH]]).to eq [1, 0, 0, 0]
|
40
|
-
expect(result[[__FILE__, line + 1, :T_OBJECT]]).to eq [1, 0, 0, 0]
|
41
|
-
expect(result[[__FILE__, line + 1, :T_STRING]]).to eq [1, 0, 0, 0]
|
47
|
+
expect(result[[__FILE__, line, :T_OBJECT]]).to eq [1, 0, 0, 0, 0]
|
48
|
+
expect(result[[__FILE__, line, :T_ARRAY]]).to eq [1, 0, 0, 0, 0]
|
49
|
+
# expect(result[[__FILE__, line + 1, :T_HASH]]).to eq [1, 0, 0, 0, 0]
|
50
|
+
expect(result[[__FILE__, line + 1, :T_OBJECT]]).to eq [1, 0, 0, 0, 0]
|
51
|
+
expect(result[[__FILE__, line + 1, :T_STRING]]).to eq [1, 0, 0, 0, 0]
|
42
52
|
end
|
43
53
|
|
44
54
|
it 'should work with class' do
|
@@ -50,11 +60,11 @@ describe ObjectSpace::AllocationTracer do
|
|
50
60
|
end
|
51
61
|
|
52
62
|
expect(result.length).to be 5
|
53
|
-
expect(result[[__FILE__, line, Object]]).to eq [1, 0, 0, 0]
|
54
|
-
expect(result[[__FILE__, line, Array]]).to eq [1, 0, 0, 0]
|
55
|
-
expect(result[[__FILE__, line + 1, Hash]]).to eq [1, 0, 0, 0]
|
56
|
-
expect(result[[__FILE__, line + 1, Object]]).to eq [1, 0, 0, 0]
|
57
|
-
expect(result[[__FILE__, line + 1, String]]).to eq [1, 0, 0, 0]
|
63
|
+
expect(result[[__FILE__, line, Object]]).to eq [1, 0, 0, 0, 0]
|
64
|
+
expect(result[[__FILE__, line, Array]]).to eq [1, 0, 0, 0, 0]
|
65
|
+
# expect(result[[__FILE__, line + 1, Hash]]).to eq [1, 0, 0, 0, 0]
|
66
|
+
expect(result[[__FILE__, line + 1, Object]]).to eq [1, 0, 0, 0, 0]
|
67
|
+
expect(result[[__FILE__, line + 1, String]]).to eq [1, 0, 0, 0, 0]
|
58
68
|
end
|
59
69
|
end
|
60
70
|
end
|