heap_dump 0.0.16 → 0.0.17
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/Rakefile +13 -0
- data/ext/heap_dump/heap_dump.c +128 -95
- data/lib/heap_dump/version.rb +1 -1
- metadata +8 -8
data/Rakefile
CHANGED
@@ -9,6 +9,19 @@ desc "Simple dump test,just to check if extension compiles and does not segfault
|
|
9
9
|
task :test => :compile do
|
10
10
|
require "bundler/setup"
|
11
11
|
require 'heap_dump'
|
12
|
+
|
13
|
+
def some_meth
|
14
|
+
fiber_var = :some_fiber_var2
|
15
|
+
Fiber.yield
|
16
|
+
aaa
|
17
|
+
end
|
18
|
+
|
19
|
+
Fiber.new{
|
20
|
+
fiber_var = :some_fiber_var
|
21
|
+
some_meth
|
22
|
+
Fiber.yield
|
23
|
+
fiber_var = :some_fiber_var3
|
24
|
+
}.resume
|
12
25
|
puts "Dumping..."
|
13
26
|
HeapDump.dump
|
14
27
|
end
|
data/ext/heap_dump/heap_dump.c
CHANGED
@@ -606,7 +606,6 @@ typedef struct rb_fiber_struct {
|
|
606
606
|
|
607
607
|
|
608
608
|
|
609
|
-
|
610
609
|
static void yg_fiber_status(enum fiber_status status, walk_ctx_t* ctx){
|
611
610
|
switch(status){
|
612
611
|
case CREATED: yg_cstring("CREATED"); break;
|
@@ -615,104 +614,28 @@ static void yg_fiber_status(enum fiber_status status, walk_ctx_t* ctx){
|
|
615
614
|
}
|
616
615
|
}
|
617
616
|
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
VALUE *sp = th->cfp->sp;
|
624
|
-
rb_control_frame_t *cfp = th->cfp;
|
625
|
-
rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
|
626
|
-
|
627
|
-
yg_cstring("stack");
|
628
|
-
yajl_gen_array_open(ctx->yajl);
|
629
|
-
while (p < sp) yg_id(*p++);
|
630
|
-
yajl_gen_array_close(ctx->yajl);
|
631
|
-
|
632
|
-
yg_cstring("cfp");
|
633
|
-
yajl_gen_array_open(ctx->yajl);
|
634
|
-
while (cfp != limit_cfp) {
|
635
|
-
yajl_gen_map_open(ctx->yajl);
|
636
|
-
rb_iseq_t *iseq = cfp->iseq;
|
637
|
-
ygh_id("proc", cfp->proc);
|
638
|
-
ygh_id("self", cfp->self);
|
639
|
-
if (iseq) {
|
640
|
-
ygh_id("iseq", RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq);
|
641
|
-
int line_no = rb_vm_get_sourceline(cfp);
|
642
|
-
ygh_rstring("file", iseq->filename);
|
643
|
-
ygh_int("line_no",line_no);
|
644
|
-
}
|
645
|
-
if (cfp->me){
|
646
|
-
const rb_method_entry_t *me = cfp->me;
|
647
|
-
//((rb_method_entry_t *)cfp->me)->mark = 1;
|
648
|
-
yg_cstring("me");
|
649
|
-
yajl_gen_map_open(ctx->yajl);
|
650
|
-
//
|
651
|
-
//rb_method_flag_t flag;
|
652
|
-
// char mark;
|
653
|
-
//rb_method_definition_t *def;
|
654
|
-
ygh_id("klass", me->klass);
|
655
|
-
ID id = me->called_id;
|
656
|
-
|
657
|
-
if(me->def){
|
658
|
-
id = me->def->original_id;
|
659
|
-
yg_cstring("def");
|
660
|
-
dump_method_definition_as_value(me->def, ctx);
|
661
|
-
}
|
662
|
-
if(id != ID_ALLOCATOR)
|
663
|
-
ygh_rstring("meth_id", rb_id2str(id));
|
664
|
-
yajl_gen_map_close(ctx->yajl);
|
665
|
-
}
|
666
|
-
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
667
|
-
yajl_gen_map_close(ctx->yajl);
|
668
|
-
}
|
669
|
-
yajl_gen_array_close(ctx->yajl);
|
670
|
-
}
|
671
|
-
|
672
|
-
//TODO: mark other...
|
673
|
-
ygh_id("first_proc", th->first_proc);
|
674
|
-
if (th->first_proc) ygh_id("first_proc", th->first_args);
|
675
|
-
|
676
|
-
ygh_id("thgroup", th->thgroup);
|
677
|
-
ygh_id("value", th->value);
|
678
|
-
ygh_id("errinfo", th->errinfo);
|
679
|
-
ygh_id("thrown_errinfo", th->thrown_errinfo);
|
680
|
-
ygh_id("local_svar", th->local_svar);
|
681
|
-
ygh_id("top_self", th->top_self);
|
682
|
-
ygh_id("top_wrapper", th->top_wrapper);
|
683
|
-
ygh_id("fiber", th->fiber);
|
684
|
-
ygh_id("root_fiber", th->root_fiber);
|
685
|
-
ygh_id("stat_insn_usage", th->stat_insn_usage);
|
686
|
-
ygh_id("last_status", th->last_status);
|
687
|
-
ygh_id("locking_mutex", th->locking_mutex);
|
688
|
-
|
689
|
-
// rb_mark_tbl(th->local_storage);
|
690
|
-
|
691
|
-
// if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) {
|
692
|
-
// rb_gc_mark_machine_stack(th);
|
693
|
-
// rb_gc_mark_locations((VALUE *)&th->machine_regs,
|
694
|
-
// (VALUE *)(&th->machine_regs) +
|
695
|
-
// sizeof(th->machine_regs) / sizeof(VALUE));
|
696
|
-
// }
|
697
|
-
|
698
|
-
yg_cstring("local_storage");
|
699
|
-
yajl_gen_array_open(ctx->yajl);
|
700
|
-
if(th->local_storage){
|
701
|
-
st_foreach(th->local_storage, dump_iv_entry, ctx); //?
|
617
|
+
static void yg_fiber_type(enum context_type status, walk_ctx_t* ctx){
|
618
|
+
switch(status){
|
619
|
+
case CONTINUATION_CONTEXT: yg_cstring("CONTINUATION_CONTEXT"); break;
|
620
|
+
case FIBER_CONTEXT: yg_cstring("FIBER_CONTEXT"); break;
|
621
|
+
case ROOT_FIBER_CONTEXT: yg_cstring("ROOT_FIBER_CONTEXT"); break;
|
702
622
|
}
|
703
|
-
|
623
|
+
}
|
704
624
|
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
625
|
+
static void dump_locations(VALUE* p, int n, walk_ctx_t *ctx){
|
626
|
+
if(n > 0){
|
627
|
+
VALUE* x = p;
|
628
|
+
while(n--){
|
629
|
+
VALUE v = *x;
|
630
|
+
if(is_pointer_to_heap(v, NULL)) //TODO: sometimes thread is known, may get its th->vm->objspace (in case there's a few)
|
631
|
+
yg_id(v);
|
632
|
+
x++;
|
633
|
+
}
|
712
634
|
}
|
713
|
-
yajl_gen_array_close(ctx->yajl);
|
714
635
|
}
|
715
636
|
|
637
|
+
static void dump_thread(rb_thread_t* th, walk_ctx_t *ctx);
|
638
|
+
|
716
639
|
|
717
640
|
|
718
641
|
static void dump_data_if_known(VALUE obj, walk_ctx_t *ctx){
|
@@ -851,11 +774,14 @@ static void dump_data_if_known(VALUE obj, walk_ctx_t *ctx){
|
|
851
774
|
rb_fiber_t *fib = RTYPEDDATA_DATA(obj);
|
852
775
|
ygh_id("prev", fib->prev);
|
853
776
|
//ygh_int("cont", fib->cont);
|
777
|
+
yg_cstring("status");
|
778
|
+
yg_fiber_status(fib->status, ctx);
|
779
|
+
|
854
780
|
yg_cstring("cont");
|
855
781
|
yg_map();
|
856
782
|
//ygh_int("type", fib->cont.type);
|
857
783
|
yg_cstring("type");
|
858
|
-
|
784
|
+
yg_fiber_type(fib->cont.type, ctx);
|
859
785
|
|
860
786
|
ygh_id("self", fib->cont.self);
|
861
787
|
ygh_id("value", fib->cont.value);
|
@@ -1466,6 +1392,113 @@ is_pointer_to_heap(void *ptr, void* osp)
|
|
1466
1392
|
return FALSE;
|
1467
1393
|
}
|
1468
1394
|
|
1395
|
+
static void dump_thread(rb_thread_t* th, walk_ctx_t *ctx){
|
1396
|
+
if(th->stack){
|
1397
|
+
VALUE *p = th->stack;
|
1398
|
+
VALUE *sp = th->cfp->sp;
|
1399
|
+
rb_control_frame_t *cfp = th->cfp;
|
1400
|
+
rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
|
1401
|
+
|
1402
|
+
yg_cstring("stack");
|
1403
|
+
yajl_gen_array_open(ctx->yajl);
|
1404
|
+
while (p < sp) yg_id(*p++);
|
1405
|
+
yajl_gen_array_close(ctx->yajl);
|
1406
|
+
yg_cstring("stack_locations");
|
1407
|
+
yg_array();
|
1408
|
+
dump_locations(p, th->mark_stack_len, ctx);
|
1409
|
+
yg_array_end();
|
1410
|
+
|
1411
|
+
yg_cstring("cfp");
|
1412
|
+
yajl_gen_array_open(ctx->yajl);
|
1413
|
+
while (cfp != limit_cfp) {
|
1414
|
+
yajl_gen_map_open(ctx->yajl);
|
1415
|
+
rb_iseq_t *iseq = cfp->iseq;
|
1416
|
+
ygh_id("proc", cfp->proc);
|
1417
|
+
ygh_id("self", cfp->self);
|
1418
|
+
if (iseq) {
|
1419
|
+
ygh_id("iseq", RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq);
|
1420
|
+
int line_no = rb_vm_get_sourceline(cfp);
|
1421
|
+
ygh_rstring("file", iseq->filename);
|
1422
|
+
ygh_int("line_no",line_no);
|
1423
|
+
}
|
1424
|
+
if (cfp->me){
|
1425
|
+
const rb_method_entry_t *me = cfp->me;
|
1426
|
+
//((rb_method_entry_t *)cfp->me)->mark = 1;
|
1427
|
+
yg_cstring("me");
|
1428
|
+
yajl_gen_map_open(ctx->yajl);
|
1429
|
+
//
|
1430
|
+
//rb_method_flag_t flag;
|
1431
|
+
// char mark;
|
1432
|
+
//rb_method_definition_t *def;
|
1433
|
+
ygh_id("klass", me->klass);
|
1434
|
+
ID id = me->called_id;
|
1435
|
+
|
1436
|
+
if(me->def){
|
1437
|
+
id = me->def->original_id;
|
1438
|
+
yg_cstring("def");
|
1439
|
+
dump_method_definition_as_value(me->def, ctx);
|
1440
|
+
}
|
1441
|
+
if(id != ID_ALLOCATOR)
|
1442
|
+
ygh_rstring("meth_id", rb_id2str(id));
|
1443
|
+
yajl_gen_map_close(ctx->yajl);
|
1444
|
+
}
|
1445
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
1446
|
+
yajl_gen_map_close(ctx->yajl);
|
1447
|
+
}
|
1448
|
+
yajl_gen_array_close(ctx->yajl);
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
//TODO: mark other...
|
1452
|
+
ygh_id("first_proc", th->first_proc);
|
1453
|
+
if (th->first_proc) ygh_id("first_proc", th->first_args);
|
1454
|
+
|
1455
|
+
ygh_id("thgroup", th->thgroup);
|
1456
|
+
ygh_id("value", th->value);
|
1457
|
+
ygh_id("errinfo", th->errinfo);
|
1458
|
+
ygh_id("thrown_errinfo", th->thrown_errinfo);
|
1459
|
+
ygh_id("local_svar", th->local_svar);
|
1460
|
+
ygh_id("top_self", th->top_self);
|
1461
|
+
ygh_id("top_wrapper", th->top_wrapper);
|
1462
|
+
ygh_id("fiber", th->fiber);
|
1463
|
+
ygh_id("root_fiber", th->root_fiber);
|
1464
|
+
ygh_id("stat_insn_usage", th->stat_insn_usage);
|
1465
|
+
ygh_id("last_status", th->last_status);
|
1466
|
+
ygh_id("locking_mutex", th->locking_mutex);
|
1467
|
+
|
1468
|
+
if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) {
|
1469
|
+
// rb_gc_mark_machine_stack(th);
|
1470
|
+
VALUE *stack_start, *stack_end;
|
1471
|
+
GET_STACK_BOUNDS(stack_start, stack_end, 0);
|
1472
|
+
// /sizeof(VALUE)?
|
1473
|
+
yg_cstring("mach_stack");
|
1474
|
+
yg_array();
|
1475
|
+
dump_locations(stack_start, (stack_end-stack_start), ctx);
|
1476
|
+
yg_array_end();
|
1477
|
+
|
1478
|
+
yg_cstring("mach_regs");
|
1479
|
+
yg_array();
|
1480
|
+
dump_locations((VALUE *)&th->machine_regs, sizeof(th->machine_regs) / sizeof(VALUE), ctx);
|
1481
|
+
yg_array_end();
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
yg_cstring("local_storage");
|
1485
|
+
yajl_gen_array_open(ctx->yajl);
|
1486
|
+
if(th->local_storage){
|
1487
|
+
st_foreach(th->local_storage, dump_iv_entry, ctx); //?
|
1488
|
+
}
|
1489
|
+
yajl_gen_array_close(ctx->yajl);
|
1490
|
+
|
1491
|
+
// mark_event_hooks(th->event_hooks);
|
1492
|
+
rb_event_hook_t *hook = th->event_hooks;
|
1493
|
+
yg_cstring("event_hooks");
|
1494
|
+
yajl_gen_array_open(ctx->yajl);
|
1495
|
+
while(hook){
|
1496
|
+
yg_id(hook->data);
|
1497
|
+
hook = hook->next;
|
1498
|
+
}
|
1499
|
+
yajl_gen_array_close(ctx->yajl);
|
1500
|
+
}
|
1501
|
+
|
1469
1502
|
|
1470
1503
|
static void dump_machine_context(walk_ctx_t *ctx){
|
1471
1504
|
//TODO: other threads?
|
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.17
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby-internal
|
16
|
-
requirement: &
|
16
|
+
requirement: &70233944233020 !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: *70233944233020
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: yajl-ruby
|
27
|
-
requirement: &
|
27
|
+
requirement: &70233944231400 !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: *70233944231400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake-compiler
|
38
|
-
requirement: &
|
38
|
+
requirement: &70233944230620 !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: *70233944230620
|
47
47
|
description: dump ruby 1.9 heap contents
|
48
48
|
email:
|
49
49
|
- vasilyfedoseyev@gmail.com
|