heap_dump 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -89,6 +89,33 @@ bt field is ruby builtin type name.
89
89
  Where available - val/refs/ivs/etc. field present with hash/array of references.
90
90
  Long numbers usually are object ids.
91
91
 
92
+ ## What may leak
93
+
94
+ ### Brief Ruby GC decription
95
+ (brief) Ruby has mark-and-sweep GC, this means that it does not leak in traditional way when you lose some pointer and do not free memory.
96
+ Ruby leaks references. But also it is different from reference counting GC, like one in python.
97
+
98
+ For example, 3 objects:
99
+
100
+ ```
101
+ A -> B -> C
102
+ ```
103
+ let's assume that A is a global variable or is referenced in stack. In this chain C does not get freed bacause it has a reference path from global/stack.
104
+
105
+ If reference to B gets deleted (for example A.b = nil):
106
+
107
+ ```
108
+ A B -> C
109
+ ```
110
+ C still is referenced by something, but both B and C will be freed, as there's no path.
111
+
112
+ ### Examples of references
113
+
114
+ Obvious references: from variables, instance variables (including class), arrays, hashes, etc.
115
+
116
+ Less obvious: method closures. These are stored in T_DATAs with 'VM/env' type.
117
+ Latest version of heap_dump allows to trace such references: search for a env, by it's id you can find it's owner iseq, which usually has file and line number where block/lambda/proc was created.
118
+
92
119
  ## Contributing
93
120
 
94
121
  1. Fork it
@@ -118,7 +118,7 @@ static void yg_id1(VALUE obj, walk_ctx_t* ctx){
118
118
  }
119
119
  if (obj == Qundef) { yg_cstring("(undef)"); return; }
120
120
 
121
- printf("immediate p %p?\n", obj);
121
+ printf("immediate p %p?\n", (void*)obj);
122
122
  yg_cstring("(unknown)");
123
123
  return;
124
124
  } else /*non-immediate*/ {
@@ -346,15 +346,14 @@ static void dump_node_refs(NODE* obj, walk_ctx_t* ctx){
346
346
 
347
347
  //iteration func - blocks,procs,lambdas etc:
348
348
  case NODE_IFUNC: //NEN_CFNC, NEN_TVAL, NEN_STATE? / u2 seems to be data for func(context?)
349
- printf("IFUNC NODE: %p %p %p\n", obj->nd_cfnc, obj->u2.node, (void*)obj->nd_aid /*u3 - aid id- - aka frame_this_func?*/);
350
- //FIXME: closures may leak references?
349
+ //printf("IFUNC NODE: %p %p %p\n", obj->nd_cfnc, obj->u2.node, (void*)obj->nd_aid /*u3 - aid id- - aka frame_this_func?*/);
351
350
  if(is_pointer_to_heap(obj->u2.node, 0)){
352
- printf("in heap: %p\n", obj->u2.node);
351
+ //printf("in heap: %p\n", obj->u2.node);
353
352
  //TODO: do we need to dump it inline?
354
- yg_id(obj->u2.node);
353
+ yg_id((VALUE)obj->u2.node);
355
354
  }
356
355
  if(is_pointer_to_heap( (void*)obj->nd_aid, 0)){
357
- printf("in heap: %p\n", (void*)obj->nd_aid);
356
+ //printf("in heap: %p\n", (void*)obj->nd_aid);
358
357
  yg_id(obj->nd_aid);
359
358
  }
360
359
  break;
@@ -489,14 +488,14 @@ static const char* iseq_type(VALUE type){
489
488
  case ISEQ_TYPE_MAIN: return "main";
490
489
  case ISEQ_TYPE_DEFINED_GUARD: return "defined_guard";
491
490
  }
492
- printf("unknown iseq type %d!\n", type);
491
+ printf("unknown iseq type %p!\n", (void*)type);
493
492
  return "unknown";
494
493
  }
495
494
 
496
495
  static void dump_iseq(const rb_iseq_t* iseq, walk_ctx_t *ctx){
497
496
  if(iseq->name) ygh_rstring("name", iseq->name);
498
497
  if(iseq->filename) ygh_rstring("filename", iseq->filename);
499
- ygh_int("line", iseq->line_no);
498
+ ygh_int("line", FIX2INT(iseq->line_no));
500
499
 
501
500
  //if(iseq->type != 25116) //also 28 in mark_ary
502
501
  ygh_cstring("type", iseq_type(iseq->type));
@@ -556,6 +555,7 @@ static void dump_data_if_known(VALUE obj, walk_ctx_t *ctx){
556
555
  if(proc->block.iseq && !RUBY_VM_IFUNC_P(proc->block.iseq)) {
557
556
  yg_cstring("iseq");
558
557
  yajl_gen_map_open(ctx->yajl);
558
+ //FIXME: id may be different (due to RBasic fields)!!!
559
559
  ygh_id("id", proc->block.iseq);
560
560
  dump_iseq(proc->block.iseq, ctx);
561
561
  yajl_gen_map_close(ctx->yajl);
@@ -1,3 +1,3 @@
1
1
  module HeapDump
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heap_dump
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-05-31 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-internal
16
- requirement: &70250067931780 !ruby/object:Gem::Requirement
16
+ requirement: &70141930337500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.8.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70250067931780
24
+ version_requirements: *70141930337500
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: yajl-ruby
27
- requirement: &70250067931200 !ruby/object:Gem::Requirement
27
+ requirement: &70141930336660 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.1'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70250067931200
35
+ version_requirements: *70141930336660
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake-compiler
38
- requirement: &70250067930760 !ruby/object:Gem::Requirement
38
+ requirement: &70141930335600 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70250067930760
46
+ version_requirements: *70141930335600
47
47
  description: dump ruby 1.9 heap contents
48
48
  email:
49
49
  - vasilyfedoseyev@gmail.com