heap_dump 0.0.9 → 0.0.10
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.
- data/README.md +27 -0
- data/ext/heap_dump/heap_dump.c +8 -8
- data/lib/heap_dump/version.rb +1 -1
- metadata +7 -7
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
|
data/ext/heap_dump/heap_dump.c
CHANGED
@@ -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 %
|
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);
|
data/lib/heap_dump/version.rb
CHANGED
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.
|
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: &
|
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: *
|
24
|
+
version_requirements: *70141930337500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: yajl-ruby
|
27
|
-
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: *
|
35
|
+
version_requirements: *70141930336660
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake-compiler
|
38
|
-
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: *
|
46
|
+
version_requirements: *70141930335600
|
47
47
|
description: dump ruby 1.9 heap contents
|
48
48
|
email:
|
49
49
|
- vasilyfedoseyev@gmail.com
|