gc_tracer 0.0.3 → 0.0.4
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 +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
|