gc_tracer 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -16
- data/ext/gc_tracer/extconf.rb +34 -0
- data/ext/gc_tracer/gc_tracer.c +152 -26
- data/lib/gc_tracer/version.rb +1 -1
- 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: 7e2224716adf83bacd915712295bff64908c6882
|
4
|
+
data.tar.gz: 35b0457e38603a400919853ceb78c5e61f2b77b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 929d796e853d3d94daaa56e79883f89ddd77a976d7a937024cda3a1313b8e06059cfef1955330bc32a8b2b6ab97f11a0ed8fc9726c1b4bf918472b7c2246e99a
|
7
|
+
data.tar.gz: 69e5f21a252131b256069fe5b1a90c56900e58cbc469610684b26a74d8214bc559faf58f42fcf0a2a2d274fa24b2904d16aac929c75b78f9a43f87617ff0d409
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# GC::Tracer
|
2
2
|
|
3
|
-
|
4
|
-
all statistics information.
|
3
|
+
Trace Garbage Collector activities and output statistics information.
|
5
4
|
|
6
5
|
This gem only supports MRI 2.1.0 and later.
|
7
6
|
|
@@ -21,25 +20,32 @@ Or install it yourself as:
|
|
21
20
|
|
22
21
|
## Usage
|
23
22
|
|
24
|
-
You can get GC statistics information like
|
23
|
+
You can get GC statistics information in block form like this:
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
```ruby
|
26
|
+
require 'gc_tracer'
|
27
|
+
GC::Tracer.start_logging(filename) do
|
28
|
+
# do something
|
29
|
+
end
|
30
|
+
```
|
30
31
|
|
31
32
|
This code is equivalent to the following code.
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
```ruby
|
35
|
+
require 'gc_tracer'
|
36
|
+
GC::Tracer.start_logging(filename)
|
37
|
+
# do something
|
38
|
+
GC::Tracer.stop_logging
|
39
|
+
```
|
37
40
|
|
38
|
-
In the stored file, you can get tab separated values about
|
39
|
-
GC.latest_gc_info() at each events
|
40
|
-
of marking time" and "end of sweeping time". For one GC, three lines
|
41
|
-
you can get.
|
41
|
+
In the stored file (filename), you can get tab separated values about
|
42
|
+
`GC.stat()` and `GC.latest_gc_info()` at each events, there are one of:
|
42
43
|
|
44
|
+
* GC starting time
|
45
|
+
* End of marking time
|
46
|
+
* End of sweeping time
|
47
|
+
|
48
|
+
For one GC, you can get all three lines.
|
43
49
|
|
44
50
|
## Contributing
|
45
51
|
|
data/ext/gc_tracer/extconf.rb
CHANGED
@@ -1,20 +1,54 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
3
|
# auto generation script
|
4
|
+
rusage_members = []
|
5
|
+
|
6
|
+
if have_header('sys/time.h') && have_header('sys/resource.h') && have_func('getrusage')
|
7
|
+
%w(ru_maxrss
|
8
|
+
ru_ixrss
|
9
|
+
ru_idrss
|
10
|
+
ru_isrss
|
11
|
+
ru_minflt
|
12
|
+
ru_majflt
|
13
|
+
ru_nswap
|
14
|
+
ru_inblock
|
15
|
+
ru_oublock
|
16
|
+
ru_msgsnd
|
17
|
+
ru_msgrcv
|
18
|
+
ru_nsignals
|
19
|
+
ru_nvcsw
|
20
|
+
ru_nivcsw).each{|member|
|
21
|
+
if have_struct_member('struct rusage', member, %w(sys/time.h sys/resource.h))
|
22
|
+
rusage_members << member
|
23
|
+
end
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
4
27
|
open("gc_tracer.h", 'w'){|f|
|
5
28
|
f.puts '#include "ruby/ruby.h"'
|
6
29
|
f.puts "static VALUE sym_gc_stat[#{GC.stat.keys.size}];"
|
7
30
|
f.puts "static VALUE sym_latest_gc_info[#{GC.latest_gc_info.keys.size}];"
|
31
|
+
unless rusage_members.empty?
|
32
|
+
f.puts "static VALUE sym_rusage_timeval[2];"
|
33
|
+
f.puts "static VALUE sym_rusage[#{rusage_members.length}];" if rusage_members.length > 0
|
34
|
+
end
|
8
35
|
|
9
36
|
f.puts "static void"
|
10
37
|
f.puts "setup_gc_trace_symbols(void)"
|
11
38
|
f.puts "{"
|
39
|
+
#
|
12
40
|
GC.stat.keys.each.with_index{|k, i|
|
13
41
|
f.puts " sym_gc_stat[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
|
14
42
|
}
|
15
43
|
GC.latest_gc_info.keys.each.with_index{|k, i|
|
16
44
|
f.puts " sym_latest_gc_info[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
|
17
45
|
}
|
46
|
+
f.puts " sym_rusage_timeval[0] = ID2SYM(rb_intern(\"ru_utime\"));"
|
47
|
+
f.puts " sym_rusage_timeval[1] = ID2SYM(rb_intern(\"ru_utime\"));"
|
48
|
+
rusage_members.each.with_index{|k, i|
|
49
|
+
f.puts " sym_rusage[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
|
50
|
+
}
|
51
|
+
#
|
18
52
|
f.puts "}"
|
19
53
|
}
|
20
54
|
|
data/ext/gc_tracer/gc_tracer.c
CHANGED
@@ -15,9 +15,18 @@ static VALUE gc_trace_enabled;
|
|
15
15
|
static FILE *gc_trace_out = NULL;
|
16
16
|
static VALUE gc_trace_items, gc_trace_items_types;
|
17
17
|
|
18
|
+
#ifdef HAVE_GETRUSAGE
|
19
|
+
#include <sys/time.h>
|
20
|
+
#include <sys/resource.h>
|
21
|
+
#endif
|
22
|
+
|
18
23
|
enum gc_key_type {
|
19
24
|
GC_STAT_KEY,
|
20
|
-
GC_LATEST_GC_INFO_KEY
|
25
|
+
GC_LATEST_GC_INFO_KEY,
|
26
|
+
#ifdef HAVE_GETRUSAGE
|
27
|
+
GC_RUSAGE_TIMEVAL_KEY,
|
28
|
+
GC_RUSAGE_KEY,
|
29
|
+
#endif
|
21
30
|
};
|
22
31
|
|
23
32
|
/* the following code is only for internal tuning. */
|
@@ -129,10 +138,105 @@ out_header(void)
|
|
129
138
|
out_terminate();
|
130
139
|
}
|
131
140
|
|
141
|
+
#ifdef HAVE_GETRUSAGE
|
142
|
+
struct rusage_cache {
|
143
|
+
int cached;
|
144
|
+
struct rusage usage;
|
145
|
+
};
|
146
|
+
|
147
|
+
static void
|
148
|
+
getursage_fill(struct rusage_cache *rusage_cache)
|
149
|
+
{
|
150
|
+
if (!rusage_cache->cached) {
|
151
|
+
rusage_cache->cached = 1;
|
152
|
+
getrusage(RUSAGE_SELF, &rusage_cache->usage);
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
static double
|
157
|
+
timeval2double(struct timeval *tv)
|
158
|
+
{
|
159
|
+
return tv->tv_sec * 1000000 + tv->tv_usec;
|
160
|
+
}
|
161
|
+
|
162
|
+
static double
|
163
|
+
getrusage_timeval(VALUE sym, struct rusage_cache *rusage_cache)
|
164
|
+
{
|
165
|
+
getursage_fill(rusage_cache);
|
166
|
+
|
167
|
+
if (sym == sym_rusage_timeval[0]) {
|
168
|
+
return timeval2double(&rusage_cache->usage.ru_utime);
|
169
|
+
}
|
170
|
+
if (sym == sym_rusage_timeval[1]) {
|
171
|
+
return timeval2double(&rusage_cache->usage.ru_stime);
|
172
|
+
}
|
173
|
+
|
174
|
+
rb_raise(rb_eRuntimeError, "getrusage_timeval: unknown symbol");
|
175
|
+
return 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
static size_t
|
179
|
+
getrusage_sizet(VALUE sym, struct rusage_cache *rusage_cache)
|
180
|
+
{
|
181
|
+
int i = 0;
|
182
|
+
|
183
|
+
getursage_fill(rusage_cache);
|
184
|
+
|
185
|
+
#if HAVE_ST_RU_MAXRSS
|
186
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_maxrss;
|
187
|
+
#endif
|
188
|
+
#if HAVE_ST_RU_IXRSS
|
189
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_ixrss;
|
190
|
+
#endif
|
191
|
+
#if HAVE_ST_RU_IDRSS
|
192
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_idrss;
|
193
|
+
#endif
|
194
|
+
#if HAVE_ST_RU_ISRSS
|
195
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_isrss;
|
196
|
+
#endif
|
197
|
+
#if HAVE_ST_RU_MINFLT
|
198
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_minflt;
|
199
|
+
#endif
|
200
|
+
#if HAVE_ST_RU_MAJFLT
|
201
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_majflt;
|
202
|
+
#endif
|
203
|
+
#if HAVE_ST_RU_NSWAP
|
204
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_nswap;
|
205
|
+
#endif
|
206
|
+
#if HAVE_ST_RU_INBLOCK
|
207
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_inblock;
|
208
|
+
#endif
|
209
|
+
#if HAVE_ST_RU_OUBLOCK
|
210
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_oublock;
|
211
|
+
#endif
|
212
|
+
#if HAVE_ST_RU_MSGSND
|
213
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_msgsnd;
|
214
|
+
#endif
|
215
|
+
#if HAVE_ST_RU_MSGRCV
|
216
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_msgrcv;
|
217
|
+
#endif
|
218
|
+
#if HAVE_ST_RU_NSIGNALS
|
219
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_nsignals;
|
220
|
+
#endif
|
221
|
+
#if HAVE_ST_RU_NVCSW
|
222
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_nvcsw;
|
223
|
+
#endif
|
224
|
+
#if HAVE_ST_RU_NIVCSW
|
225
|
+
if (sym == sym_rusage[i++]) return rusage_cache->usage.ru_nivcsw;
|
226
|
+
#endif
|
227
|
+
|
228
|
+
rb_raise(rb_eRuntimeError, "getrusage_sizet: unknown symbol");
|
229
|
+
return 0;
|
230
|
+
}
|
231
|
+
#endif
|
232
|
+
|
132
233
|
static void
|
133
234
|
trace(const char *type)
|
134
235
|
{
|
135
236
|
int i;
|
237
|
+
#ifdef HAVE_GETRUSAGE
|
238
|
+
struct rusage_cache rusage_cache = {0};
|
239
|
+
#endif
|
136
240
|
|
137
241
|
out_tick();
|
138
242
|
out_str(type);
|
@@ -148,6 +252,14 @@ trace(const char *type)
|
|
148
252
|
case GC_LATEST_GC_INFO_KEY:
|
149
253
|
out_obj(rb_gc_latest_gc_info(sym));
|
150
254
|
break;
|
255
|
+
#ifdef HAVE_GETRUSAGE
|
256
|
+
case GC_RUSAGE_TIMEVAL_KEY:
|
257
|
+
out_sizet((size_t)getrusage_timeval(sym, &rusage_cache));
|
258
|
+
break;
|
259
|
+
case GC_RUSAGE_KEY:
|
260
|
+
out_sizet(getrusage_sizet(sym, &rusage_cache));
|
261
|
+
break;
|
262
|
+
#endif
|
151
263
|
default:
|
152
264
|
rb_bug("xyzzy");
|
153
265
|
}
|
@@ -244,12 +356,20 @@ static enum gc_key_type
|
|
244
356
|
item_type(VALUE sym)
|
245
357
|
{
|
246
358
|
int i;
|
247
|
-
for (i=0; i<(int)(sizeof(sym_gc_stat)/sizeof(VALUE));i++) {
|
248
|
-
return GC_STAT_KEY;
|
359
|
+
for (i=0; i<(int)(sizeof(sym_gc_stat)/sizeof(VALUE)); i++) {
|
360
|
+
if (sym_gc_stat[i] == sym) return GC_STAT_KEY;
|
361
|
+
}
|
362
|
+
for (i=0; i<(int)(sizeof(sym_latest_gc_info)/sizeof(VALUE)); i++) {
|
363
|
+
if (sym_latest_gc_info[i] == sym) return GC_LATEST_GC_INFO_KEY;
|
249
364
|
}
|
250
|
-
|
251
|
-
|
365
|
+
#ifdef HAVE_GETRUSAGE
|
366
|
+
for (i=0; i<(int)(sizeof(sym_rusage_timeval)/sizeof(VALUE)); i++) {
|
367
|
+
if (sym_rusage_timeval[i] == sym) return GC_RUSAGE_TIMEVAL_KEY;
|
252
368
|
}
|
369
|
+
for (i=0; i<(int)(sizeof(sym_rusage)/sizeof(VALUE)); i++) {
|
370
|
+
if (sym_rusage[i] == sym) return GC_RUSAGE_KEY;
|
371
|
+
}
|
372
|
+
#endif
|
253
373
|
rb_raise(rb_eArgError, "Unknown key type");
|
254
374
|
return 0; /* unreachable */
|
255
375
|
}
|
@@ -260,19 +380,35 @@ gc_tracer_setup_logging(VALUE self, VALUE ary)
|
|
260
380
|
int i;
|
261
381
|
VALUE keys = rb_ary_new(), types = rb_ary_new();
|
262
382
|
|
263
|
-
if (
|
383
|
+
if (NIL_P(ary)) { /* revert all settings */
|
384
|
+
int i;
|
264
385
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
386
|
+
#define ADD(syms) for (i=0; i<(int)(sizeof(syms)/sizeof(VALUE));i++) { \
|
387
|
+
rb_ary_push(gc_trace_items, syms[i]); \
|
388
|
+
rb_ary_push(gc_trace_items_types, INT2FIX(item_type(syms[i]))); \
|
389
|
+
}
|
390
|
+
ADD(sym_gc_stat);
|
391
|
+
ADD(sym_latest_gc_info);
|
392
|
+
#ifdef HAVE_GETRUSAGE
|
393
|
+
ADD(sym_rusage_timeval);
|
394
|
+
ADD(sym_rusage);
|
395
|
+
#endif
|
272
396
|
}
|
397
|
+
else {
|
398
|
+
if (!RB_TYPE_P(ary, T_ARRAY)) rb_raise(rb_eArgError, "unsupported argument");
|
399
|
+
|
400
|
+
for (i=0; i<RARRAY_LEN(ary); i++) {
|
401
|
+
VALUE sym = RARRAY_AREF(ary, i);
|
402
|
+
enum gc_key_type type;
|
403
|
+
if (!SYMBOL_P(sym)) rb_raise(rb_eArgError, "unsupported type");
|
404
|
+
type = item_type(sym);
|
405
|
+
rb_ary_push(keys, sym);
|
406
|
+
rb_ary_push(types, INT2FIX(type));
|
407
|
+
}
|
273
408
|
|
274
|
-
|
275
|
-
|
409
|
+
rb_ary_replace(gc_trace_items, keys);
|
410
|
+
rb_ary_replace(gc_trace_items_types, types);
|
411
|
+
}
|
276
412
|
return Qnil;
|
277
413
|
}
|
278
414
|
|
@@ -296,15 +432,5 @@ Init_gc_tracer(void)
|
|
296
432
|
rb_gc_register_mark_object(gc_trace_items);
|
297
433
|
rb_gc_register_mark_object(gc_trace_items_types);
|
298
434
|
|
299
|
-
|
300
|
-
int i;
|
301
|
-
for (i=0; i<(int)(sizeof(sym_gc_stat)/sizeof(VALUE));i++) {
|
302
|
-
rb_ary_push(gc_trace_items, sym_gc_stat[i]);
|
303
|
-
rb_ary_push(gc_trace_items_types, INT2FIX(GC_STAT_KEY));
|
304
|
-
}
|
305
|
-
for (i=0; i<(int)(sizeof(sym_latest_gc_info)/sizeof(VALUE));i++) {
|
306
|
-
rb_ary_push(gc_trace_items, sym_latest_gc_info[i]);
|
307
|
-
rb_ary_push(gc_trace_items_types, INT2FIX(GC_LATEST_GC_INFO_KEY));
|
308
|
-
}
|
309
|
-
}
|
435
|
+
gc_tracer_setup_logging(Qnil, Qnil);
|
310
436
|
}
|
data/lib/gc_tracer/version.rb
CHANGED
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: 0.0.
|
4
|
+
version: 0.0.4
|
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-03-
|
11
|
+
date: 2014-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|