allocation_tracer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ec726b2a738166d01a261edd355fe34d8a727af
4
- data.tar.gz: 4bcfe98dad9c2e41621992b780a60c419f710b70
3
+ metadata.gz: e1f129686d0942e7690ff66568f9af7f50f11148
4
+ data.tar.gz: fbc17e5b8358996aa55843c8632e15896d14f16d
5
5
  SHA512:
6
- metadata.gz: 0c2195f1424ca3220e939519b79130a4baad68993643fd895d1c26433d313876738372232cdd12df1a673b6d248af736647d11c0d35ed2018996ee49dad6927d
7
- data.tar.gz: 6a28c18f2c5a943c28cbde895f020dfe7cc8e4542c83bdf3d8b05058d7210d7ee6f3ff8fffcd055ed65e374bd9e5f88b82fb980747a02b2b9c873cef91997dec
6
+ metadata.gz: 886adb15a4f94f3fd9ed2815f9aee9fa524bf48aa853ceafb9bf2ff450a5dcd204ce8b8c483029ba78d1bc81f2124e7bb6662770d253e2aed58262c24a54e8ad
7
+ data.tar.gz: 69b0c17158f3f8af672296a4868c609a2f12c0c8b8d10d08b7d2309c6357b35b2b9f843986594c62bfad1549a62aeae12f90e9cfe3db3c299ee59f5001b07b00
data/README.md CHANGED
@@ -26,7 +26,16 @@ Or install it yourself as:
26
26
 
27
27
  ### Allocation tracing
28
28
 
29
- You can trace allocation information and you can get aggregated information.
29
+ You can trace allocation and aggregate information. Information includes:
30
+
31
+ count - how many objects are created.
32
+ total_age - total age of objects which created here
33
+ max_age - age of longest living object created here
34
+ min_age - age of shortest living object created here
35
+
36
+ Age of Object can be calculated by this formula: [current GC count] - [birth time GC count]
37
+
38
+ For example:
30
39
 
31
40
  ```ruby
32
41
  require 'allocation_tracer'
@@ -15,7 +15,6 @@ struct allocation_info {
15
15
  int living;
16
16
  VALUE flags;
17
17
  VALUE klass;
18
- const char *klass_path;
19
18
  size_t generation;
20
19
 
21
20
  /* allocation info */
@@ -188,7 +187,6 @@ static void
188
187
  free_allocation_info(struct traceobj_arg *arg, struct allocation_info *info)
189
188
  {
190
189
  delete_unique_str(arg->str_table, info->path);
191
- delete_unique_str(arg->str_table, info->klass_path);
192
190
  ruby_xfree(info);
193
191
  }
194
192
 
@@ -199,12 +197,9 @@ newobj_i(VALUE tpval, void *data)
199
197
  struct allocation_info *info;
200
198
  rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
201
199
  VALUE obj = rb_tracearg_object(tparg);
202
- VALUE klass = RBASIC_CLASS(obj);
203
200
  VALUE path = rb_tracearg_path(tparg);
204
201
  VALUE line = rb_tracearg_lineno(tparg);
205
- VALUE klass_path = (RTEST(klass) && !OBJ_FROZEN(klass)) ? rb_class_path_cached(klass) : Qnil;
206
202
  const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : NULL;
207
- const char *klass_path_cstr = RTEST(klass_path) ? make_unique_str(arg->str_table, RSTRING_PTR(klass_path), RSTRING_LEN(klass_path)) : NULL;
208
203
 
209
204
  if (st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
210
205
  if (info->living) {
@@ -212,7 +207,6 @@ newobj_i(VALUE tpval, void *data)
212
207
  }
213
208
  /* reuse info */
214
209
  delete_unique_str(arg->str_table, info->path);
215
- delete_unique_str(arg->str_table, info->klass_path);
216
210
  }
217
211
  else {
218
212
  info = create_allocation_info();
@@ -221,8 +215,7 @@ newobj_i(VALUE tpval, void *data)
221
215
  info->next = NULL;
222
216
  info->living = 1;
223
217
  info->flags = RBASIC(obj)->flags;
224
- info->klass = klass;
225
- info->klass_path = klass_path_cstr;
218
+ info->klass = rb_class_real(RBASIC_CLASS(obj));
226
219
  info->generation = rb_gc_count();
227
220
 
228
221
  info->path = path_cstr;
@@ -262,7 +255,7 @@ aggregator_i(void *data)
262
255
  key_data.data[i++] = (st_data_t)(info->flags & T_MASK);
263
256
  }
264
257
  if (arg->keys & KEY_CLASS) {
265
- key_data.data[i++] = (st_data_t)info->klass_path;
258
+ key_data.data[i++] = info->klass;
266
259
  }
267
260
  key_data.n = i;
268
261
  key = (st_data_t)&key_data;
@@ -282,7 +275,6 @@ aggregator_i(void *data)
282
275
  val_buff[2] = val_buff[3] = age;
283
276
 
284
277
  if (arg->keys & KEY_PATH) keep_unique_str(arg->str_table, info->path);
285
- if (arg->keys & KEY_CLASS) keep_unique_str(arg->str_table, info->klass_path);
286
278
 
287
279
  st_insert(arg->aggregate_table, (st_data_t)key_buff, (st_data_t)val_buff);
288
280
  }
@@ -301,11 +293,10 @@ aggregator_i(void *data)
301
293
  }
302
294
 
303
295
  static void
304
- move_to_freed_list(struct traceobj_arg *arg, VALUE obj, struct allocation_info *info)
296
+ move_to_freed_list(struct traceobj_arg *arg, struct allocation_info *info)
305
297
  {
306
298
  info->next = arg->freed_allocation_info;
307
299
  arg->freed_allocation_info = info;
308
- st_delete(arg->object_table, (st_data_t *)&obj, (st_data_t *)&info);
309
300
  }
310
301
 
311
302
  static void
@@ -321,7 +312,8 @@ freeobj_i(VALUE tpval, void *data)
321
312
  }
322
313
 
323
314
  if (st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
324
- move_to_freed_list(arg, obj, info);
315
+ move_to_freed_list(arg, info);
316
+ st_delete(arg->object_table, (st_data_t *)&obj, (st_data_t *)&info);
325
317
  }
326
318
  }
327
319
 
@@ -422,10 +414,12 @@ aggregate_result_i(st_data_t key, st_data_t val, void *data)
422
414
  rb_ary_push(k, type_symbols[key_buff->data[i++]]);
423
415
  }
424
416
  if (arg->keys & KEY_CLASS) {
425
- const char *klass_path = (const char *)key_buff->data[i++];
426
- if (klass_path) {
427
-
428
- delete_unique_str(arg->str_table, klass_path);
417
+ VALUE klass = key_buff->data[i++];
418
+ if (BUILTIN_TYPE(klass) == T_CLASS) {
419
+ klass = rb_class_real(klass);
420
+ rb_ary_push(k, klass);
421
+ /* TODO: actually, it is dangerous code because klass can be sweeped */
422
+ /* So that class specifier is hidden feature */
429
423
  }
430
424
  else {
431
425
  rb_ary_push(k, Qnil);
@@ -442,7 +436,7 @@ aggregate_rest_object_i(st_data_t key, st_data_t val, void *data)
442
436
  {
443
437
  struct traceobj_arg *arg = (struct traceobj_arg *)data;
444
438
  struct allocation_info *info = (struct allocation_info *)val;
445
- move_to_freed_list(arg, (VALUE)key, info);
439
+ move_to_freed_list(arg, info);
446
440
  return ST_CONTINUE;
447
441
  }
448
442
 
@@ -454,6 +448,7 @@ aggregate_result(struct traceobj_arg *arg)
454
448
  aar.arg = arg;
455
449
 
456
450
  st_foreach(arg->object_table, aggregate_rest_object_i, (st_data_t)arg);
451
+ st_clear(arg->object_table);
457
452
  aggregator_i(arg);
458
453
  st_foreach(arg->aggregate_table, aggregate_result_i, (st_data_t)&aar);
459
454
  clear_traceobj_arg();
@@ -521,6 +516,8 @@ allocation_tracer_setup(int argc, VALUE *argv, VALUE self)
521
516
  int i;
522
517
  VALUE ary = rb_check_array_type(argv[0]);
523
518
 
519
+ arg->keys = 0;
520
+
524
521
  for (i=0; i<(int)RARRAY_LEN(ary); i++) {
525
522
  if (RARRAY_AREF(ary, i) == ID2SYM(rb_intern("path"))) arg->keys |= KEY_PATH;
526
523
  else if (RARRAY_AREF(ary, i) == ID2SYM(rb_intern("line"))) arg->keys |= KEY_LINE;
@@ -1,3 +1,3 @@
1
1
  module ObjectSpace::AllocationTracer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -23,5 +23,39 @@ describe ObjectSpace::AllocationTracer do
23
23
  expect(result.length).to be >= 1
24
24
  expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0]
25
25
  end
26
+
27
+ describe 'with different setup' do
28
+ it 'should work with type' do
29
+ line = __LINE__ + 3
30
+ ObjectSpace::AllocationTracer.setup(%i(path line type))
31
+ result = ObjectSpace::AllocationTracer.trace do
32
+ a = [Object.new]
33
+ b = {Object.new => 'foo'}
34
+ end
35
+
36
+ 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]
42
+ end
43
+
44
+ it 'should work with class' do
45
+ line = __LINE__ + 3
46
+ ObjectSpace::AllocationTracer.setup(%i(path line class))
47
+ result = ObjectSpace::AllocationTracer.trace do
48
+ a = [Object.new]
49
+ b = {Object.new => 'foo'}
50
+ end
51
+
52
+ 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]
58
+ end
59
+ end
26
60
  end
27
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allocation_tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Sasada