allocation_tracer 0.3.2 → 0.3.3
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 +4 -4
- data/README.md +27 -24
- data/ext/allocation_tracer/allocation_tracer.c +34 -9
- data/lib/allocation_tracer/version.rb +1 -1
- data/lib/allocation_tracer.rb +13 -1
- data/spec/allocation_tracer_spec.rb +17 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a8521b2ac3ab75ead4770b8aa3b9982f8467d84
|
4
|
+
data.tar.gz: a4b23c68be89223a669d149cf08bd6105cbcaf7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58e5ab416b474b20fedef2a0a99e39d0da0dde7074f50a28047e0205240aa4ae660e9c4df114acfcacf496d657d6cc660b8fbaf4353369c5d400b3b70ab14d78
|
7
|
+
data.tar.gz: c4176f951ee62200e6e4faace8b9c5e7d0240d8bf4217a868d120758eed8725ba007e059d7af62c7bfe1835a18b953a46cb7adf3db9b23863d4cc9a5ca336776
|
data/README.md
CHANGED
@@ -30,10 +30,10 @@ Or install it yourself as:
|
|
30
30
|
|
31
31
|
You can trace allocation and aggregate information. Information includes:
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
* count - how many objects are created.
|
34
|
+
* total_age - total age of objects which created here
|
35
|
+
* max_age - age of longest living object created here
|
36
|
+
* min_age - age of shortest living object created here
|
37
37
|
|
38
38
|
Age of Object can be calculated by this formula: [current GC count] - [birth time GC count]
|
39
39
|
|
@@ -55,14 +55,17 @@ pp ObjectSpace::AllocationTracer.trace{
|
|
55
55
|
will show
|
56
56
|
|
57
57
|
```
|
58
|
-
{["test.rb", 6]=>[50000,
|
59
|
-
["test.rb", 7]=>[50000,
|
60
|
-
["test.rb", 8]=>[50000,
|
58
|
+
{["test.rb", 6]=>[50000, 0, 47440, 0, 1, 0],
|
59
|
+
["test.rb", 7]=>[50000, 4, 47452, 0, 6, 0],
|
60
|
+
["test.rb", 8]=>[50000, 7, 47456, 0, 6, 0]}
|
61
61
|
```
|
62
62
|
|
63
|
-
In this case,
|
64
|
-
|
65
|
-
|
63
|
+
In this case,
|
64
|
+
* 50,000 objects are created at `test.rb:6' and
|
65
|
+
* 5 old objects created.
|
66
|
+
* 44,290 is total age of objects created at this line (average age of object created at this line is 50000/44290 = 0.8858).
|
67
|
+
* 0 is minimum age
|
68
|
+
* 6 is maximum age.
|
66
69
|
|
67
70
|
You can also specify `type' in GC::Tracer.setup_allocation_tracing() to
|
68
71
|
specify what should be keys to aggregate like that.
|
@@ -87,12 +90,12 @@ pp result
|
|
87
90
|
and you will get:
|
88
91
|
|
89
92
|
```
|
90
|
-
{["test.rb", 8, :T_STRING]=>[50000,
|
91
|
-
["test.rb", 8, :T_ARRAY]=>[50000,
|
92
|
-
["test.rb", 9, :T_STRING]=>[100000,
|
93
|
-
["test.rb", 9, :T_HASH]=>[50000,
|
94
|
-
["test.rb", 10, :T_STRING]=>[100000,
|
95
|
-
["test.rb", 10, :T_STRUCT]=>[50000,
|
93
|
+
{["test.rb", 8, :T_STRING]=>[50000, 15, 49165, 0, 16, 0],
|
94
|
+
["test.rb", 8, :T_ARRAY]=>[50000, 12, 49134, 0, 16, 0],
|
95
|
+
["test.rb", 9, :T_STRING]=>[100000, 27, 98263, 0, 16, 0],
|
96
|
+
["test.rb", 9, :T_HASH]=>[50000, 16, 49147, 0, 16, 8998848],
|
97
|
+
["test.rb", 10, :T_STRING]=>[100000, 36, 98322, 0, 16, 0],
|
98
|
+
["test.rb", 10, :T_STRUCT]=>[50000, 16, 49147, 0, 16, 0]}
|
96
99
|
```
|
97
100
|
|
98
101
|
Interestingly, you can not see array creations in a middle of block:
|
@@ -116,7 +119,7 @@ pp result
|
|
116
119
|
and it prints:
|
117
120
|
|
118
121
|
```
|
119
|
-
{["test.rb", 8, :T_STRING]=>[
|
122
|
+
{["test.rb", 8, :T_STRING]=>[25015, 5, 16299, 0, 2, 0]}
|
120
123
|
```
|
121
124
|
|
122
125
|
There are only string creation. This is because unused array creation is
|
@@ -140,13 +143,13 @@ require 'allocation_tracer/trace'
|
|
140
143
|
and you will see:
|
141
144
|
|
142
145
|
```
|
143
|
-
path line count total_age max_age
|
144
|
-
|
145
|
-
|
146
|
-
test.rb 0 1 0 0 0
|
147
|
-
test.rb 5 50000
|
148
|
-
test.rb 6 50000
|
149
|
-
test.rb 7 50000
|
146
|
+
path line count old_count total_age min_age max_age total_memsize
|
147
|
+
...rubygems/core_ext/kernel_require.rb 55 18 1 23 1 6 358
|
148
|
+
...lib/allocation_tracer/lib/allocation_tracer/trace.rb 6 2 012 6 6 0
|
149
|
+
test.rb 0 1 0 0 0 0 0
|
150
|
+
test.rb 5 50000 4 41492 0 5 0
|
151
|
+
test.rb 6 50000 3 41490 0 5 0
|
152
|
+
test.rb 7 50000 7 41497 0 5 0
|
150
153
|
```
|
151
154
|
|
152
155
|
(tab separated colums)
|
@@ -526,6 +526,7 @@ type_sym(int type)
|
|
526
526
|
}
|
527
527
|
|
528
528
|
struct arg_and_result {
|
529
|
+
int update;
|
529
530
|
struct traceobj_arg *arg;
|
530
531
|
VALUE result;
|
531
532
|
};
|
@@ -536,14 +537,9 @@ aggregate_result_i(st_data_t key, st_data_t val, void *data)
|
|
536
537
|
struct arg_and_result *aar = (struct arg_and_result *)data;
|
537
538
|
struct traceobj_arg *arg = aar->arg;
|
538
539
|
VALUE result = aar->result;
|
539
|
-
|
540
540
|
size_t *val_buff = (size_t *)val;
|
541
541
|
struct memcmp_key_data *key_buff = (struct memcmp_key_data *)key;
|
542
|
-
VALUE v =
|
543
|
-
INT2FIX(val_buff[0]), INT2FIX(val_buff[1]),
|
544
|
-
INT2FIX(val_buff[2]), INT2FIX(val_buff[3]),
|
545
|
-
INT2FIX(val_buff[4]), INT2FIX(val_buff[5]));
|
546
|
-
VALUE k = rb_ary_new();
|
542
|
+
VALUE v, oldv, k = rb_ary_new();
|
547
543
|
int i = 0;
|
548
544
|
|
549
545
|
i = 0;
|
@@ -577,6 +573,25 @@ aggregate_result_i(st_data_t key, st_data_t val, void *data)
|
|
577
573
|
}
|
578
574
|
}
|
579
575
|
|
576
|
+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
577
|
+
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
578
|
+
|
579
|
+
if (aar->update && (oldv = rb_hash_aref(result, k)) != Qnil) {
|
580
|
+
v = rb_ary_new3(6,
|
581
|
+
INT2FIX(val_buff[0] + FIX2INT(RARRAY_AREF(oldv, 0))), /* count */
|
582
|
+
INT2FIX(val_buff[1] + FIX2INT(RARRAY_AREF(oldv, 1))), /* old count */
|
583
|
+
INT2FIX(val_buff[2] + FIX2INT(RARRAY_AREF(oldv, 2))), /* total_age */
|
584
|
+
INT2FIX(MIN(val_buff[3], FIX2INT(RARRAY_AREF(oldv, 3)))), /* min age */
|
585
|
+
INT2FIX(MAX(val_buff[4], FIX2INT(RARRAY_AREF(oldv, 4)))), /* max age */
|
586
|
+
INT2FIX(val_buff[5] + FIX2INT(RARRAY_AREF(oldv, 5)))); /* memsize_of */
|
587
|
+
}
|
588
|
+
else {
|
589
|
+
v = rb_ary_new3(6,
|
590
|
+
INT2FIX(val_buff[0]), INT2FIX(val_buff[1]),
|
591
|
+
INT2FIX(val_buff[2]), INT2FIX(val_buff[3]),
|
592
|
+
INT2FIX(val_buff[4]), INT2FIX(val_buff[5]));
|
593
|
+
}
|
594
|
+
|
580
595
|
rb_hash_aset(result, k, v);
|
581
596
|
|
582
597
|
return ST_CONTINUE;
|
@@ -627,6 +642,12 @@ lifetime_table_for_live_objects_i(st_data_t key, st_data_t val, st_data_t data)
|
|
627
642
|
return ST_CONTINUE;
|
628
643
|
}
|
629
644
|
|
645
|
+
static int
|
646
|
+
st_size(struct st_table *st)
|
647
|
+
{
|
648
|
+
return st->num_bins;
|
649
|
+
}
|
650
|
+
|
630
651
|
static VALUE
|
631
652
|
aggregate_result(struct traceobj_arg *arg)
|
632
653
|
{
|
@@ -634,11 +655,14 @@ aggregate_result(struct traceobj_arg *arg)
|
|
634
655
|
aar.result = rb_hash_new();
|
635
656
|
aar.arg = arg;
|
636
657
|
|
637
|
-
|
638
|
-
|
658
|
+
while (arg->freed_allocation_info) {
|
659
|
+
aggregate_freed_info(arg);
|
660
|
+
}
|
661
|
+
|
662
|
+
/* collect from recent-freed objects */
|
663
|
+
aar.update = 0;
|
639
664
|
st_foreach(arg->aggregate_table, aggregate_result_i, (st_data_t)&aar);
|
640
665
|
|
641
|
-
/* collect live aggregate table */
|
642
666
|
{
|
643
667
|
st_table *dead_object_aggregate_table = arg->aggregate_table;
|
644
668
|
|
@@ -647,6 +671,7 @@ aggregate_result(struct traceobj_arg *arg)
|
|
647
671
|
st_foreach(arg->object_table, aggregate_live_object_i, (st_data_t)arg);
|
648
672
|
|
649
673
|
/* aggregate table -> Ruby hash */
|
674
|
+
aar.update = 1;
|
650
675
|
st_foreach(arg->aggregate_table, aggregate_result_i, (st_data_t)&aar);
|
651
676
|
|
652
677
|
/* remove live object aggregate table */
|
data/lib/allocation_tracer.rb
CHANGED
@@ -2,6 +2,16 @@ require "allocation_tracer/version"
|
|
2
2
|
require "allocation_tracer/allocation_tracer"
|
3
3
|
|
4
4
|
module ObjectSpace::AllocationTracer
|
5
|
+
|
6
|
+
def self.output_lifetime_table table
|
7
|
+
out = (file = ENV['RUBY_ALLOCATION_TRACER_LIFETIME_OUT']) ? open(File.expand_path(file), 'w') : STDOUT
|
8
|
+
max_lines = table.inject(0){|r, (type, lines)| r < lines.size ? lines.size : r}
|
9
|
+
out.puts "type\t" + (0...max_lines).to_a.join("\t")
|
10
|
+
table.each{|type, line|
|
11
|
+
out.puts "#{type}\t#{line.join("\t")}"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
5
15
|
def self.collect_lifetime_talbe
|
6
16
|
ObjectSpace::AllocationTracer.lifetime_table_setup true
|
7
17
|
|
@@ -10,7 +20,8 @@ module ObjectSpace::AllocationTracer
|
|
10
20
|
ObjectSpace::AllocationTracer.trace do
|
11
21
|
yield
|
12
22
|
end
|
13
|
-
ObjectSpace::AllocationTracer.lifetime_table
|
23
|
+
result = ObjectSpace::AllocationTracer.lifetime_table
|
24
|
+
output_lifetime_table(result)
|
14
25
|
ensure
|
15
26
|
ObjectSpace::AllocationTracer.lifetime_table_setup false
|
16
27
|
end
|
@@ -23,6 +34,7 @@ module ObjectSpace::AllocationTracer
|
|
23
34
|
ObjectSpace::AllocationTracer.stop
|
24
35
|
result = ObjectSpace::AllocationTracer.lifetime_table
|
25
36
|
ObjectSpace::AllocationTracer.lifetime_table_setup false
|
37
|
+
output_lifetime_table(result)
|
26
38
|
result
|
27
39
|
end
|
28
40
|
end
|
@@ -25,6 +25,23 @@ describe ObjectSpace::AllocationTracer do
|
|
25
25
|
expect(result[[__FILE__, line]]).to eq [1, 0, 0, 0, 0, 0]
|
26
26
|
end
|
27
27
|
|
28
|
+
it 'should analyze many objects' do
|
29
|
+
line = __LINE__ + 3
|
30
|
+
result = ObjectSpace::AllocationTracer.trace do
|
31
|
+
50_000.times{|i|
|
32
|
+
i.to_s
|
33
|
+
i.to_s
|
34
|
+
i.to_s
|
35
|
+
}
|
36
|
+
end
|
37
|
+
#GC.start
|
38
|
+
#pp result
|
39
|
+
|
40
|
+
expect(result[[__FILE__, line + 0]][0]).to be >= 50_000
|
41
|
+
expect(result[[__FILE__, line + 1]][0]).to be >= 50_000
|
42
|
+
expect(result[[__FILE__, line + 2]][0]).to be >= 50_000
|
43
|
+
end
|
44
|
+
|
28
45
|
it 'should count old objects' do
|
29
46
|
a = nil
|
30
47
|
line = __LINE__ + 2
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: allocation_tracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Sasada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|