allocation_tracer 0.0.1 → 0.0.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 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