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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7f8ebd99820c0f4376283b1a2ef31eb4b5ca9f25
4
- data.tar.gz: 87d80cbb89a799728380ff6fde872295c9daad8a
3
+ metadata.gz: 7e2224716adf83bacd915712295bff64908c6882
4
+ data.tar.gz: 35b0457e38603a400919853ceb78c5e61f2b77b7
5
5
  SHA512:
6
- metadata.gz: 335152d1fc8d18e4ebd143e6f95afe398753368bae91b85cc43d9353d2f400daf566108252d40ec750b630bdaf04cdc8047791885d9898cb778f899f87cbb826
7
- data.tar.gz: 3a75ee2d7c0aad3516d778cad11fa5e7a1d0be8ec94cf5c597159d9e9b94a5fe68b7283ada3d2a0192c4ec937aa956196e87925832b08839437913c4ee92f158
6
+ metadata.gz: 929d796e853d3d94daaa56e79883f89ddd77a976d7a937024cda3a1313b8e06059cfef1955330bc32a8b2b6ab97f11a0ed8fc9726c1b4bf918472b7c2246e99a
7
+ data.tar.gz: 69e5f21a252131b256069fe5b1a90c56900e58cbc469610684b26a74d8214bc559faf58f42fcf0a2a2d274fa24b2904d16aac929c75b78f9a43f87617ff0d409
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
- # GcTracer
1
+ # GC::Tracer
2
2
 
3
- gc-tracer gem add GC::Tracer module which trace GC activities and output
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 that:
23
+ You can get GC statistics information in block form like this:
25
24
 
26
- require 'gc_tracer'
27
- GC::Tracer.start_logging(filename) do
28
- # do something
29
- end
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
- require 'gc_tracer'
34
- GC::Tracer.start_logging(filename)
35
- # do something
36
- GC::Tracer.stop_logging
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 GC.stat() and
39
- GC.latest_gc_info() at each events. Events are "GC starting time", "end
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
 
@@ -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
 
@@ -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
- for (i=0; i<(int)(sizeof(sym_latest_gc_info)/sizeof(VALUE));i++) {
251
- return GC_LATEST_GC_INFO_KEY;
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 (!RB_TYPE_P(ary, T_ARRAY)) rb_raise(rb_eArgError, "unsupported argument");
383
+ if (NIL_P(ary)) { /* revert all settings */
384
+ int i;
264
385
 
265
- for (i=0; i<RARRAY_LEN(ary); i++) {
266
- VALUE sym = RARRAY_AREF(ary, i);
267
- enum gc_key_type type;
268
- if (!SYMBOL_P(sym)) rb_raise(rb_eArgError, "unsupported type");
269
- type = item_type(sym);
270
- rb_ary_push(keys, sym);
271
- rb_ary_push(types, INT2FIX(type));
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
- rb_ary_replace(gc_trace_items, keys);
275
- rb_ary_replace(gc_trace_items_types, types);
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
  }
@@ -1,3 +1,3 @@
1
1
  module GcTracer
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
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.3
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-25 00:00:00.000000000 Z
11
+ date: 2014-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler