gc_tracer 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.md +36 -8
- data/ext/gc_tracer/gc_logging.c +122 -0
- data/lib/gc_tracer.rb +4 -1
- data/lib/gc_tracer/version.rb +1 -1
- data/spec/gc_tracer_spec.rb +72 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08efc028ba431a430f1e0d1ac444b74884e575b4
|
4
|
+
data.tar.gz: 04aa0ea80b8ce757cd32bce97a84644740c6a53c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 299a15128bd5794000a3d631e5ca21132dbe954192f19c71c5b5a18f3332271646375d108be07b516ef7f803dab65fcd932e862e435e9a3ba7ddd3c0329e95af
|
7
|
+
data.tar.gz: b6132a320def13c6161a4dcc7e105c21f167c82e6ad03af303dd4f9f2f9a00b874c8e253bf3f864a0978737d2673e588f946087faae8307e368eca702208e3e6
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -4,6 +4,8 @@ Trace Garbage Collector activities and output statistics information.
|
|
4
4
|
|
5
5
|
This gem only supports MRI 2.1.0 and later.
|
6
6
|
|
7
|
+
[![Build Status](https://travis-ci.org/ko1/gc_tracer.svg)](https://travis-ci.org/ko1/gc_tracer)
|
8
|
+
|
7
9
|
## Installation
|
8
10
|
|
9
11
|
Add this line to your application's Gemfile:
|
@@ -80,7 +82,7 @@ ensure
|
|
80
82
|
end
|
81
83
|
```
|
82
84
|
|
83
|
-
Default events are "start", "end_mark" and "end_sweep". You can specify
|
85
|
+
Default events are "start", "end_mark" and "end_sweep". You can specify
|
84
86
|
what kind of information you want to collect.
|
85
87
|
|
86
88
|
```ruby
|
@@ -93,22 +95,48 @@ ensure
|
|
93
95
|
end
|
94
96
|
```
|
95
97
|
|
96
|
-
Above example means that no details information are not needed. Default
|
98
|
+
Above example means that no details information are not needed. Default
|
97
99
|
setting is "gc_stat: true, gc_latest_gc_info: true, rusage: false".
|
98
100
|
|
99
|
-
You can specify tick (time stamp) type with keyword parameter
|
100
|
-
"tick_type". You can choose one of the tick type in :hw_counter, :time
|
101
|
+
You can specify tick (time stamp) type with keyword parameter
|
102
|
+
"tick_type". You can choose one of the tick type in :hw_counter, :time
|
101
103
|
and :nano_time (if platform supports clock_gettime()).
|
102
104
|
|
103
105
|
See lib/gc_tracer.rb for more details.
|
104
106
|
|
107
|
+
### Custom fields
|
108
|
+
|
109
|
+
You can add custom fields.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
GC::Tracer.start_logging(custom_fields: [:name1, :name2, ...]) do
|
113
|
+
# All fields are cleared by zero.
|
114
|
+
|
115
|
+
# You can increment values of each field.
|
116
|
+
GC::Tracer.custom_field_increment(:name1)
|
117
|
+
# It is equivalent to
|
118
|
+
# GC::Tracer.custom_field_set(:name1, GC::Tracer.custom_field_get(:name1))
|
119
|
+
|
120
|
+
# You can also decrement values
|
121
|
+
GC::Tracer.custom_field_decrement(:name1)
|
122
|
+
|
123
|
+
# Now, you can specify only Fixnum as field value.
|
124
|
+
GC::Tracer.custom_field_set(:name2, 123)
|
125
|
+
|
126
|
+
# You can specify an index instead of field name (faster than actual name)
|
127
|
+
GC::Tracer.custom_field_increment(0) # :name1
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
Custom fields are printed as last columns.
|
132
|
+
|
105
133
|
### Custom events
|
106
134
|
|
107
|
-
You can add custom events by your own. Calling
|
108
|
-
`GC::Tracer.custom_event_logging(event_name)` in your program will puts
|
135
|
+
You can add custom events by your own. Calling
|
136
|
+
`GC::Tracer.custom_event_logging(event_name)` in your program will puts
|
109
137
|
new statistics line into the logging file.
|
110
138
|
|
111
|
-
For example, the following program insert 1000 custom event lines into
|
139
|
+
For example, the following program insert 1000 custom event lines into
|
112
140
|
logging file (stderr for this type).
|
113
141
|
|
114
142
|
```ruby
|
@@ -120,7 +148,7 @@ GC::Tracer.start_logging(events: %i(start), gc_stat: false) do
|
|
120
148
|
end
|
121
149
|
```
|
122
150
|
|
123
|
-
This method is useful to trace where the GC events occur in your
|
151
|
+
This method is useful to trace where the GC events occur in your
|
124
152
|
application.
|
125
153
|
|
126
154
|
|
data/ext/gc_tracer/gc_logging.c
CHANGED
@@ -66,6 +66,8 @@ tick(void)
|
|
66
66
|
#define MAX_HOOKS 5
|
67
67
|
#endif
|
68
68
|
|
69
|
+
#define MAX_CUSTOM_FIELDS 128
|
70
|
+
|
69
71
|
static VALUE tracer_hooks[MAX_HOOKS];
|
70
72
|
static VALUE tracer_acceptable_events[MAX_HOOKS];
|
71
73
|
|
@@ -77,12 +79,16 @@ struct gc_logging {
|
|
77
79
|
int log_gc_stat;
|
78
80
|
int log_gc_latest_gc_info;
|
79
81
|
int log_rusage;
|
82
|
+
int log_custom_fields_count;
|
80
83
|
} config;
|
81
84
|
|
82
85
|
int enabled;
|
83
86
|
VALUE enable_hooks[MAX_HOOKS]; /* Symbols */
|
84
87
|
int enable_hooks_num; /* 0 to MAX_HOOKS */
|
85
88
|
|
89
|
+
ID custom_field_names[MAX_CUSTOM_FIELDS];
|
90
|
+
long custom_field_values[MAX_CUSTOM_FIELDS];
|
91
|
+
|
86
92
|
FILE *out;
|
87
93
|
const char *event;
|
88
94
|
|
@@ -138,6 +144,12 @@ out_sizet(FILE *out, size_t size)
|
|
138
144
|
fprintf(out, "%lu\t", (unsigned long)size);
|
139
145
|
}
|
140
146
|
|
147
|
+
static void
|
148
|
+
out_long(FILE *out, long l)
|
149
|
+
{
|
150
|
+
fprintf(out, "%ld\t", l);
|
151
|
+
}
|
152
|
+
|
141
153
|
static double
|
142
154
|
timeval2double(struct timeval *tv)
|
143
155
|
{
|
@@ -303,6 +315,13 @@ out_stat(struct gc_logging *logging, const char *event)
|
|
303
315
|
#if HAVE_GETRUSAGE
|
304
316
|
if (logging->config.log_rusage) out_rusage(logging);
|
305
317
|
#endif
|
318
|
+
if (logging->config.log_custom_fields_count > 0) {
|
319
|
+
int i;
|
320
|
+
for (i=0; i<logging->config.log_custom_fields_count; i++) {
|
321
|
+
out_long(logging->out, logging->custom_field_values[i]);
|
322
|
+
}
|
323
|
+
}
|
324
|
+
|
306
325
|
out_terminate(logging->out);
|
307
326
|
}
|
308
327
|
|
@@ -335,6 +354,12 @@ out_header(struct gc_logging *logging)
|
|
335
354
|
out_header_each(logging, sym_rusage, sizeof(sym_rusage)/sizeof(VALUE));
|
336
355
|
}
|
337
356
|
#endif
|
357
|
+
if (logging->config.log_custom_fields_count > 0) {
|
358
|
+
int i;
|
359
|
+
for (i=0; i<logging->config.log_custom_fields_count; i++) {
|
360
|
+
out_str(logging->out, rb_id2name(logging->custom_field_names[i]));
|
361
|
+
}
|
362
|
+
}
|
338
363
|
out_terminate(logging->out);
|
339
364
|
}
|
340
365
|
|
@@ -540,6 +565,96 @@ gc_tracer_setup_logging_rusage(VALUE self, VALUE b)
|
|
540
565
|
return self;
|
541
566
|
}
|
542
567
|
|
568
|
+
static VALUE
|
569
|
+
gc_tracer_setup_logging_custom_fields(VALUE self, VALUE b)
|
570
|
+
{
|
571
|
+
struct gc_logging *logging = &trace_logging;
|
572
|
+
|
573
|
+
if (RTEST(b)) {
|
574
|
+
VALUE ary = rb_check_array_type(b);
|
575
|
+
int i;
|
576
|
+
|
577
|
+
logging->config.log_custom_fields_count = RARRAY_LEN(ary);
|
578
|
+
|
579
|
+
for (i=0; i<RARRAY_LEN(ary); i++) {
|
580
|
+
VALUE name = RARRAY_AREF(ary, i);
|
581
|
+
ID field_id = rb_to_id(name);
|
582
|
+
|
583
|
+
if (i >= MAX_CUSTOM_FIELDS) {
|
584
|
+
rb_raise(rb_eRuntimeError, "Number of custome fields exceeds %d", MAX_CUSTOM_FIELDS);
|
585
|
+
}
|
586
|
+
|
587
|
+
logging->custom_field_names[i] = field_id;
|
588
|
+
logging->custom_field_values[i] = 0;
|
589
|
+
}
|
590
|
+
}
|
591
|
+
else {
|
592
|
+
logging->config.log_custom_fields_count = 0;
|
593
|
+
}
|
594
|
+
|
595
|
+
return self;
|
596
|
+
}
|
597
|
+
|
598
|
+
static long *
|
599
|
+
custom_field_value_place(VALUE name)
|
600
|
+
{
|
601
|
+
struct gc_logging *logging = &trace_logging;
|
602
|
+
int index;
|
603
|
+
|
604
|
+
if (FIXNUM_P(name)) {
|
605
|
+
index = FIX2INT(name);
|
606
|
+
if (index >= logging->config.log_custom_fields_count) {
|
607
|
+
rb_raise(rb_eRuntimeError, "Only %d custom fields are available, but %d was specified",
|
608
|
+
logging->config.log_custom_fields_count, index);
|
609
|
+
}
|
610
|
+
}
|
611
|
+
else {
|
612
|
+
int i;
|
613
|
+
ID nid = rb_to_id(name);
|
614
|
+
for (i=0; i<logging->config.log_custom_fields_count; i++) {
|
615
|
+
if (nid == logging->custom_field_names[i]) {
|
616
|
+
index = i;
|
617
|
+
goto found;
|
618
|
+
}
|
619
|
+
}
|
620
|
+
rb_raise(rb_eRuntimeError, "Unkown custom fileds is specified.");
|
621
|
+
}
|
622
|
+
found:
|
623
|
+
return &logging->custom_field_values[index];
|
624
|
+
}
|
625
|
+
|
626
|
+
static VALUE
|
627
|
+
gc_tracer_custom_field_increment(VALUE self, VALUE name)
|
628
|
+
{
|
629
|
+
long *valp = custom_field_value_place(name);
|
630
|
+
(*valp)++;
|
631
|
+
return self;
|
632
|
+
}
|
633
|
+
|
634
|
+
static VALUE
|
635
|
+
gc_tracer_custom_field_decrement(VALUE self, VALUE name)
|
636
|
+
{
|
637
|
+
long *valp = custom_field_value_place(name);
|
638
|
+
(*valp)--;
|
639
|
+
return self;
|
640
|
+
}
|
641
|
+
|
642
|
+
static VALUE
|
643
|
+
gc_tracer_custom_field_get(VALUE self, VALUE name)
|
644
|
+
{
|
645
|
+
long *valp = custom_field_value_place(name);
|
646
|
+
return LONG2NUM(*valp);
|
647
|
+
}
|
648
|
+
|
649
|
+
static VALUE
|
650
|
+
gc_tracer_custom_field_set(VALUE self, VALUE name, VALUE val)
|
651
|
+
{
|
652
|
+
long *valp = custom_field_value_place(name);
|
653
|
+
long lval = NUM2LONG(val);
|
654
|
+
*valp = lval;
|
655
|
+
return val;
|
656
|
+
}
|
657
|
+
|
543
658
|
static VALUE
|
544
659
|
gc_tracer_start_logging(int argc, VALUE *argv, VALUE self)
|
545
660
|
{
|
@@ -597,6 +712,13 @@ Init_gc_tracer_logging(VALUE mod)
|
|
597
712
|
rb_define_module_function(mod, "setup_logging_gc_latest_gc_info=", gc_tracer_setup_logging_gc_latest_gc_info, 1);
|
598
713
|
rb_define_module_function(mod, "setup_logging_rusage=", gc_tracer_setup_logging_rusage, 1);
|
599
714
|
|
715
|
+
/* custom fields */
|
716
|
+
rb_define_module_function(mod, "setup_looging_custom_fields=", gc_tracer_setup_logging_custom_fields, 1);
|
717
|
+
rb_define_module_function(mod, "custom_field_increment", gc_tracer_custom_field_increment, 1);
|
718
|
+
rb_define_module_function(mod, "custom_field_decrement", gc_tracer_custom_field_decrement, 1);
|
719
|
+
rb_define_module_function(mod, "custom_field_set", gc_tracer_custom_field_set, 2);
|
720
|
+
rb_define_module_function(mod, "custom_field_get", gc_tracer_custom_field_get, 1);
|
721
|
+
|
600
722
|
/* custom event */
|
601
723
|
rb_define_module_function(mod, "custom_event_logging", gc_tracer_custom_event_logging, 1);
|
602
724
|
|
data/lib/gc_tracer.rb
CHANGED
@@ -12,7 +12,9 @@ module GC
|
|
12
12
|
# collect information
|
13
13
|
gc_stat: true,
|
14
14
|
gc_latest_gc_info: true,
|
15
|
-
rusage: false
|
15
|
+
rusage: false,
|
16
|
+
custom_fields: nil
|
17
|
+
)
|
16
18
|
# setup
|
17
19
|
raise "do not specify two fienames" if filename && filename_opt
|
18
20
|
setup_logging_out(filename_opt || filename)
|
@@ -22,6 +24,7 @@ module GC
|
|
22
24
|
self.setup_logging_gc_latest_gc_info = gc_latest_gc_info
|
23
25
|
self.setup_logging_rusage = rusage
|
24
26
|
self.setup_logging_tick_type = tick_type
|
27
|
+
self.setup_looging_custom_fields = custom_fields
|
25
28
|
|
26
29
|
if block_given?
|
27
30
|
begin
|
data/lib/gc_tracer/version.rb
CHANGED
data/spec/gc_tracer_spec.rb
CHANGED
@@ -28,6 +28,78 @@ describe GC::Tracer do
|
|
28
28
|
it_behaves_like "logging_test"
|
29
29
|
end
|
30
30
|
|
31
|
+
describe 'custom fields' do
|
32
|
+
describe 'manipulate values' do
|
33
|
+
around 'open' do |example|
|
34
|
+
Dir.mktmpdir('gc_tracer'){|dir|
|
35
|
+
logfile = "#{dir}/logging"
|
36
|
+
GC::Tracer.start_logging(logfile, custom_fields: %i(a b c)) do
|
37
|
+
example.run
|
38
|
+
end
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should raise error for unknown name or index' do
|
43
|
+
expect{GC::Tracer.custom_field_increment(:xyzzy)}.to raise_error RuntimeError
|
44
|
+
expect{GC::Tracer.custom_field_increment(42)}.to raise_error RuntimeError
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should count increments' do
|
48
|
+
GC::Tracer.custom_field_increment(:a)
|
49
|
+
GC::Tracer.custom_field_increment(:a)
|
50
|
+
GC::Tracer.custom_field_increment(:a)
|
51
|
+
GC::Tracer.custom_field_increment(0)
|
52
|
+
GC::Tracer.custom_field_increment(0)
|
53
|
+
GC::Tracer.custom_field_increment(0)
|
54
|
+
|
55
|
+
expect(GC::Tracer.custom_field_get(:a)).to be 6
|
56
|
+
expect(GC::Tracer.custom_field_get(0)).to be 6
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should count decments' do
|
60
|
+
GC::Tracer.custom_field_decrement(:b)
|
61
|
+
GC::Tracer.custom_field_decrement(:b)
|
62
|
+
GC::Tracer.custom_field_decrement(:b)
|
63
|
+
GC::Tracer.custom_field_decrement(1)
|
64
|
+
GC::Tracer.custom_field_decrement(1)
|
65
|
+
GC::Tracer.custom_field_decrement(1)
|
66
|
+
|
67
|
+
expect(GC::Tracer.custom_field_get(:b)).to be -6
|
68
|
+
expect(GC::Tracer.custom_field_get(1)).to be -6
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should set values' do
|
72
|
+
GC::Tracer.custom_field_set(:c, 42)
|
73
|
+
expect(GC::Tracer.custom_field_get(:c)).to be 42
|
74
|
+
GC::Tracer.custom_field_set(2, 43)
|
75
|
+
expect(GC::Tracer.custom_field_get(:c)).to be 43
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'output custome fields' do
|
80
|
+
it 'should output custome fields' do
|
81
|
+
Dir.mktmpdir('gc_tracer'){|dir|
|
82
|
+
logfile = "#{dir}/logging"
|
83
|
+
GC::Tracer.start_logging(logfile, custom_fields: %i(a b c)) do
|
84
|
+
GC::Tracer.custom_field_increment(:a)
|
85
|
+
GC::Tracer.custom_field_decrement(:b)
|
86
|
+
GC::Tracer.custom_event_logging("out")
|
87
|
+
end
|
88
|
+
|
89
|
+
expect(File.exist?(logfile)).to be_true
|
90
|
+
log = File.read(logfile)
|
91
|
+
expect(log.lines[0]).to match /a\tb\tc/
|
92
|
+
log.each_line{|line|
|
93
|
+
if /out/ =~ line
|
94
|
+
expect(line).to match /1\t-1\t0/
|
95
|
+
end
|
96
|
+
}
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
31
103
|
=begin not supported now.
|
32
104
|
shared_examples "objspace_recorder_test" do
|
33
105
|
dirname = "gc_tracer_objspace_recorder_spec.#{$$}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gc_tracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Sasada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -76,6 +76,7 @@ extensions:
|
|
76
76
|
extra_rdoc_files: []
|
77
77
|
files:
|
78
78
|
- ".gitignore"
|
79
|
+
- ".travis.yml"
|
79
80
|
- Gemfile
|
80
81
|
- LICENSE.txt
|
81
82
|
- README.md
|
@@ -119,4 +120,3 @@ summary: gc_tracer gem adds GC::Tracer module.
|
|
119
120
|
test_files:
|
120
121
|
- spec/gc_tracer_spec.rb
|
121
122
|
- spec/spec_helper.rb
|
122
|
-
has_rdoc:
|