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 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