gc_tracer 0.3.3 → 1.0.0

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: d40ce88a683ae35d05716971bb306c3b796cf223
4
- data.tar.gz: c6b1f8d10cdb302ff382f48bcbc9ce54b0a79ecc
3
+ metadata.gz: e93e7dfe6c23589a2f0fe11353cffb53dc903632
4
+ data.tar.gz: 2cb9278fbf2b4ba77e809b05421e1c5593cb3336
5
5
  SHA512:
6
- metadata.gz: b5a14088fedc2332d5a9bcf43e0f080a7eea7875d82227dc20ed6c2fc685d1d29add57bbd68f7ecc61155cea27602e0a9f8c2351b609d07f4f2f0e8a0775b1c8
7
- data.tar.gz: 156d0e736ae8421c6fd0808dd7eef3965fa41974534cb2d06388289aef545cfa9a33deb45f04932129b18a66fa69119968f2f37719c05857943c0a532abfe996
6
+ metadata.gz: f9ae74ac0d8577dd8b48b4bfaddaeb85af2aedbf70838b0f796b6eaf65193300d6e41804d28dda93861fb4b211b6bf1c71586850a811b49c390df741b18c0543
7
+ data.tar.gz: a1c6d9e8b33f96f664894462750add5481e7ea90ef2420742ecb030b2bd39e5ac9c9dba017e5c58b8ddea99292f9ee9c4b98a2919b23337bc026eec04d0181f3
data/README.md CHANGED
@@ -23,7 +23,7 @@ Or install it yourself as:
23
23
  gc_tracer gem adds GC::Tracer module. GC::Tracer module has the following features.
24
24
 
25
25
  - Logging GC statistics information
26
- - ObjectSpace recorder
26
+ - ObjectSpace recorder (not supported yet)
27
27
 
28
28
  ### Logging
29
29
 
@@ -56,59 +56,49 @@ In the stored file (filename), you can get tab separated values of:
56
56
 
57
57
  at each events, there are one of:
58
58
 
59
- * GC starting time
60
- * End of marking time
61
- * End of sweeping time
59
+ * GC starting time (start)
60
+ * End of marking time (end_mark)
61
+ * End of sweeping time (end_sweep)
62
+ * GC enter (enter)
63
+ * GC exit (exit)
64
+ * newobj (newobj)
65
+ * freeobj (freeobj)
62
66
 
63
67
  For one GC, you can get all three lines.
64
68
 
65
- ### ObjectSpace recorder
66
-
67
- You can records objspace snapshots on each events. Snapshots are stored
68
- in the [PPM (P6) format] (http://en.wikipedia.org/wiki/Netpbm_format).
69
+ You can specify events by event name symbols you want to show.
69
70
 
70
71
  ```ruby
71
72
  require 'gc_tracer'
72
- GC::Tracer.start_objspace_recording(dirname) do
73
+ begin
74
+ GC::Tracer.start_logging(filename, events: %i(enter exit))
73
75
  # do something
76
+ ensure
77
+ GC::Tracer.stop_logging
74
78
  end
75
79
  ```
76
80
 
77
- All PPM images are stored in dirname/ppm/.
78
-
79
- If you have netpbm package and pnmtopng command,
80
- bin/objspace_recorder_convert.rb converts all ppm images into png files.
81
- Converted png images stored into dirname/png/.
82
-
83
- To view converted images, "dirname/viewer.html" is created.
84
- You can view all converted png images with "dirname/viewer.html" file in animation.
85
-
86
- This feature is supported only latest Ruby versions (2.2, and later).
87
-
88
- #### Example
81
+ Default events are "start", "end_mark" and "end_sweep". You can specify
82
+ what kind of information you want to collect.
89
83
 
90
84
  ```ruby
91
85
  require 'gc_tracer'
92
- GC::Tracer.start_objspace_recording("objspace_recorded_type_example", :type){
93
- n = 1_000
94
- m = 10_000
95
-
96
- n.times{
97
- ary = []
98
- m.times{
99
- ary << ''
100
- }
101
- }
102
- }
86
+ begin
87
+ GC::Tracer.start_logging(filename, gc_stat: false, gc_latest_gc_info: false, rusage: false)
88
+ # do something
89
+ ensure
90
+ GC::Tracer.stop_logging
91
+ end
103
92
  ```
104
93
 
105
- This program takes all snapshot of type information at each GC events.
94
+ Above example means that no details information are not needed. Default
95
+ setting is "gc_stat: true, gc_latest_gc_info: true, rusage: false".
106
96
 
107
- - :age (default) - take snapshots of age information (empty/young/old/shady)
108
- - :type - take snapshots of type information (T_???)
97
+ You can specify tick (time stamp) type with keyword parameter
98
+ "tick_type". You can choose one of the tick type in :hw_counter, :time,
99
+ :user_time and :system_time.
109
100
 
110
- You can see an [age example] (http://www.atdot.net/~ko1/gc_tracer/objspace_recorded_age_example/viewer.html) and
111
- a [type example] (http://www.atdot.net/~ko1/gc_tracer/objspace_recorded_type_example/viewer.html).
101
+ See lib/gc_tracer.rb for more details.
112
102
 
113
103
  ## Contributing
114
104
 
data/Rakefile CHANGED
@@ -15,3 +15,8 @@ task default: :spec
15
15
  task :run => 'compile' do
16
16
  ruby 'test.rb'
17
17
  end
18
+
19
+ task :gdb => 'compile' do
20
+ system('gdb --args ruby test.rb')
21
+ end
22
+
@@ -5,6 +5,7 @@
5
5
  * created at Wed Feb 26 10:52:59 2014.
6
6
  */
7
7
 
8
+ #if 0
8
9
  #include "ruby/ruby.h"
9
10
  #include "ruby/debug.h"
10
11
  #include "gc_tracer.h"
@@ -19,15 +20,18 @@ static ID id_young;
19
20
  struct gc_hooks {
20
21
  VALUE hooks[3];
21
22
  VALUE enabled;
22
- void (*funcs[3])(void *data, int event_index);
23
+ void (*funcs[3])(FILE *, void *data, int event_index);
23
24
  void *args[3];
24
25
  void *data;
26
+ FILE *out;
25
27
  };
26
28
 
27
- static const char *event_names[] = {
29
+ static const char * const event_names[] = {
28
30
  "gc_start",
29
31
  "gc_end_m",
30
- "gc_end_s"
32
+ "gc_end_s",
33
+ "gc_enter",
34
+ "gc_exit_"
31
35
  };
32
36
 
33
37
  /* common funcs */
@@ -36,21 +40,21 @@ static void
36
40
  gc_start_i(VALUE tpval, void *data)
37
41
  {
38
42
  struct gc_hooks *hooks = (struct gc_hooks *)data;
39
- (*hooks->funcs[0])(hooks->args[0], 0);
43
+ (*hooks->funcs[0])(hooks->out, hooks->args[0], 0);
40
44
  }
41
45
 
42
46
  static void
43
47
  gc_end_mark_i(VALUE tpval, void *data)
44
48
  {
45
49
  struct gc_hooks *hooks = (struct gc_hooks *)data;
46
- (*hooks->funcs[1])(hooks->args[1], 1);
50
+ (*hooks->funcs[1])(hooks->out, hooks->args[1], 1);
47
51
  }
48
52
 
49
53
  static void
50
54
  gc_end_sweep_i(VALUE tpval, void *data)
51
55
  {
52
56
  struct gc_hooks *hooks = (struct gc_hooks *)data;
53
- (*hooks->funcs[2])(hooks->args[2], 2);
57
+ (*hooks->funcs[2])(hooks->out, hooks->args[2], 2);
54
58
  }
55
59
 
56
60
  static void
@@ -95,7 +99,6 @@ stop_gc_hooks(struct gc_hooks *hooks)
95
99
  /* logger */
96
100
 
97
101
  struct gc_hooks logger;
98
- static FILE *gc_trace_out = NULL;
99
102
  static VALUE gc_trace_items, gc_trace_items_types;
100
103
 
101
104
  #ifdef HAVE_GETRUSAGE
@@ -112,113 +115,20 @@ enum gc_key_type {
112
115
  #endif
113
116
  };
114
117
 
115
- /* the following code is only for internal tuning. */
116
-
117
- /* Source code to use RDTSC is quoted and modified from
118
- * http://www.mcs.anl.gov/~kazutomo/rdtsc.html
119
- * written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
120
- */
121
-
122
- #if defined(__GNUC__) && defined(__i386__)
123
- typedef unsigned long long tick_t;
124
-
125
- static inline tick_t
126
- tick(void)
127
- {
128
- unsigned long long int x;
129
- __asm__ __volatile__ ("rdtsc" : "=A" (x));
130
- return x;
131
- }
132
-
133
- #elif defined(__GNUC__) && defined(__x86_64__)
134
- typedef unsigned long long tick_t;
135
-
136
- static __inline__ tick_t
137
- tick(void)
138
- {
139
- unsigned long hi, lo;
140
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
141
- return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32);
142
- }
143
-
144
- #elif defined(_WIN32) && defined(_MSC_VER)
145
- #include <intrin.h>
146
- typedef unsigned __int64 tick_t;
147
-
148
- static inline tick_t
149
- tick(void)
150
- {
151
- return __rdtsc();
152
- }
153
-
154
- #else /* use clock */
155
- typedef clock_t tick_t;
156
- static inline tick_t
157
- tick(void)
158
- {
159
- return clock();
160
- }
161
- #endif
162
-
163
- static tick_t start_tick;
164
118
 
165
119
  static void
166
- out_str(const char *str)
167
- {
168
- fprintf(gc_trace_out, "%s\t", str);
169
- }
170
-
171
- static void
172
- out_terminate(void)
173
- {
174
- fprintf(gc_trace_out, "\n");
175
- }
176
-
177
- static void
178
- out_sizet(size_t size)
179
- {
180
- fprintf(gc_trace_out, "%lu\t", (unsigned long)size);
181
- }
182
-
183
- static void
184
- out_tick(void)
185
- {
186
- out_sizet(tick() - start_tick);
187
- }
188
-
189
- static void
190
- out_obj(VALUE obj)
191
- {
192
- if (NIL_P(obj) || obj == Qfalse) {
193
- out_sizet(0);
194
- }
195
- else if (obj == Qtrue) {
196
- out_sizet(1);
197
- }
198
- else if (SYMBOL_P(obj)) {
199
- out_str(rb_id2name(SYM2ID(obj)));
200
- }
201
- else if (FIXNUM_P(obj)) {
202
- out_sizet(FIX2INT(obj));
203
- }
204
- else {
205
- rb_bug("out_obj: unknown object to output");
206
- }
207
- }
208
-
209
- static void
210
- out_header(void)
120
+ out_header(FILE *out, VALUE items, int need_type)
211
121
  {
212
122
  int i;
213
123
 
214
- out_str("tick");
215
- out_str("type");
124
+ out_str(out, "tick");
125
+ if (need_type) out_str(out, "type");
216
126
 
217
- for (i=0; i<RARRAY_LEN(gc_trace_items); i++) {
218
- out_str(rb_id2name(SYM2ID(RARRAY_AREF(gc_trace_items, i))));
127
+ for (i=0; i<RARRAY_LEN(items); i++) {
128
+ out_str(out, rb_id2name(SYM2ID(RARRAY_AREF(items, i))));
219
129
  }
220
130
 
221
- out_terminate();
131
+ out_terminate(out);
222
132
  }
223
133
 
224
134
  #ifdef HAVE_GETRUSAGE
@@ -314,54 +224,88 @@ getrusage_sizet(VALUE sym, struct rusage_cache *rusage_cache)
314
224
  #endif
315
225
 
316
226
  static void
317
- trace(void *data, int event_index)
227
+ out_items(FILE *out, VALUE items, VALUE items_types)
318
228
  {
319
- const char *type = (const char *)data;
320
229
  int i;
321
230
  #ifdef HAVE_GETRUSAGE
322
231
  struct rusage_cache rusage_cache = {0};
323
232
  #endif
324
233
 
325
- out_tick();
326
- out_str(type);
327
-
328
- for (i=0; i<RARRAY_LEN(gc_trace_items); i++) {
329
- enum gc_key_type type = FIX2INT(RARRAY_AREF(gc_trace_items_types, i));
330
- VALUE sym = RARRAY_AREF(gc_trace_items, i);
234
+ for (i=0; i<RARRAY_LEN(items); i++) {
235
+ enum gc_key_type type = FIX2INT(RARRAY_AREF(items_types, i));
236
+ VALUE sym = RARRAY_AREF(items, i);
331
237
 
332
238
  switch (type) {
333
239
  case GC_STAT_KEY:
334
- out_sizet(rb_gc_stat(sym));
240
+ out_sizet(out, rb_gc_stat(sym));
335
241
  break;
336
242
  case GC_LATEST_GC_INFO_KEY:
337
- out_obj(rb_gc_latest_gc_info(sym));
243
+ out_obj(out, rb_gc_latest_gc_info(sym));
338
244
  break;
339
245
  #ifdef HAVE_GETRUSAGE
340
246
  case GC_RUSAGE_TIMEVAL_KEY:
341
- out_sizet((size_t)getrusage_timeval(sym, &rusage_cache));
247
+ out_sizet(out, (size_t)getrusage_timeval(sym, &rusage_cache));
342
248
  break;
343
249
  case GC_RUSAGE_KEY:
344
- out_sizet(getrusage_sizet(sym, &rusage_cache));
250
+ out_sizet(out, getrusage_sizet(sym, &rusage_cache));
345
251
  break;
346
252
  #endif
347
253
  default:
348
254
  rb_bug("xyzzy");
349
255
  }
350
256
  }
257
+ }
351
258
 
352
- out_terminate();
259
+ static void
260
+ trace(FILE *out, void *data, int event_index)
261
+ {
262
+ const char *type = (const char *)data;
263
+
264
+ out_tick(out);
265
+ out_str(out, type);
266
+ out_items(out, gc_trace_items, gc_trace_items_types);
267
+ out_terminate(out);
268
+ }
269
+
270
+ static void
271
+ close_output(FILE *out)
272
+ {
273
+ fflush(out);
274
+ if (out != stderr) {
275
+ fclose(out);
276
+ }
277
+ }
278
+
279
+ static FILE *
280
+ open_output(int argc, VALUE *argv)
281
+ {
282
+ FILE *out = NULL;
283
+
284
+ /* setup with args */
285
+ if (argc == 0) {
286
+ out = stderr;
287
+ }
288
+ else if (argc == 1) {
289
+ if (RB_TYPE_P(argv[0], T_STRING)) {
290
+ const char *filename = StringValueCStr(argv[0]);
291
+ if ((out = fopen(filename, "w")) == NULL) {
292
+ rb_raise(rb_eRuntimeError, "can not open file: %s\n", filename);
293
+ }
294
+ }
295
+ }
296
+ else {
297
+ rb_raise(rb_eArgError, "too many arguments");
298
+ }
299
+
300
+ return out;
353
301
  }
354
302
 
355
303
  static VALUE
356
304
  gc_tracer_stop_logging(VALUE self)
357
305
  {
358
306
  if (logger.enabled) {
359
- fflush(gc_trace_out);
360
- if (gc_trace_out != stderr) {
361
- fclose(gc_trace_out);
362
- }
363
- gc_trace_out = NULL;
364
-
307
+ close_output(logger.out);
308
+ logger.out = NULL;
365
309
  stop_gc_hooks(&logger);
366
310
  }
367
311
 
@@ -374,23 +318,8 @@ gc_tracer_start_logging(int argc, VALUE *argv, VALUE self)
374
318
  if (logger.enabled == Qfalse) {
375
319
  int i;
376
320
 
377
- /* setup with args */
378
- if (argc == 0) {
379
- gc_trace_out = stderr;
380
- }
381
- else if (argc == 1) {
382
- if (RB_TYPE_P(argv[0], T_STRING)) {
383
- const char *filename = StringValueCStr(argv[0]);
384
- if ((gc_trace_out = fopen(filename, "w")) == NULL) {
385
- rb_raise(rb_eRuntimeError, "can not open file: %s\n", filename);
386
- }
387
- }
388
- }
389
- else {
390
- rb_raise(rb_eArgError, "too many arguments");
391
- }
392
-
393
- out_header();
321
+ logger.out = open_output(argc, argv);
322
+ out_header(logger.out, gc_trace_items, 1);
394
323
 
395
324
  for (i=0; i<3; i++) {
396
325
  logger.funcs[i] = trace;
@@ -430,18 +359,18 @@ item_type(VALUE sym)
430
359
  return 0; /* unreachable */
431
360
  }
432
361
 
433
- static VALUE
434
- gc_tracer_setup_logging(VALUE self, VALUE ary)
362
+ static void
363
+ setup_items(VALUE new_items, VALUE items, VALUE types)
435
364
  {
365
+ VALUE is = rb_ary_new();
366
+ VALUE ts = rb_ary_new();
436
367
  int i;
437
- VALUE keys = rb_ary_new(), types = rb_ary_new();
438
368
 
439
- if (NIL_P(ary)) { /* revert all settings */
440
- int i;
369
+ if (NIL_P(new_items)) {
441
370
 
442
371
  #define ADD(syms) for (i=0; i<(int)(sizeof(syms)/sizeof(VALUE));i++) { \
443
- rb_ary_push(gc_trace_items, syms[i]); \
444
- rb_ary_push(gc_trace_items_types, INT2FIX(item_type(syms[i]))); \
372
+ rb_ary_push(is, syms[i]); \
373
+ rb_ary_push(ts, INT2FIX(item_type(syms[i]))); \
445
374
  }
446
375
  ADD(sym_gc_stat);
447
376
  ADD(sym_latest_gc_info);
@@ -451,23 +380,94 @@ gc_tracer_setup_logging(VALUE self, VALUE ary)
451
380
  #endif
452
381
  }
453
382
  else {
454
- if (!RB_TYPE_P(ary, T_ARRAY)) rb_raise(rb_eArgError, "unsupported argument");
383
+ if (!RB_TYPE_P(new_items, T_ARRAY)) rb_raise(rb_eArgError, "unsupported argument");
455
384
 
456
- for (i=0; i<RARRAY_LEN(ary); i++) {
457
- VALUE sym = RARRAY_AREF(ary, i);
385
+ for (i=0; i<RARRAY_LEN(new_items); i++) {
386
+ VALUE sym = RARRAY_AREF(new_items, i);
458
387
  enum gc_key_type type;
459
388
  if (!SYMBOL_P(sym)) rb_raise(rb_eArgError, "unsupported type");
460
389
  type = item_type(sym);
461
- rb_ary_push(keys, sym);
462
- rb_ary_push(types, INT2FIX(type));
390
+ rb_ary_push(is, sym);
391
+ rb_ary_push(ts, INT2FIX(type));
463
392
  }
464
393
 
465
- rb_ary_replace(gc_trace_items, keys);
466
- rb_ary_replace(gc_trace_items_types, types);
394
+ }
395
+
396
+ rb_ary_replace(items, is);
397
+ rb_ary_replace(types, ts);
398
+ }
399
+
400
+ static VALUE
401
+ gc_tracer_setup_logging(VALUE self, VALUE ary)
402
+ {
403
+ setup_items(Qnil, gc_trace_items, gc_trace_items_types);
404
+ return Qnil;
405
+ }
406
+
407
+ /* slot logger */
408
+
409
+ struct slot_logger {
410
+ VALUE hook;
411
+ VALUE items;
412
+ VALUE items_types;
413
+ FILE *out;
414
+ VALUE enabled;
415
+ } slot_logger;
416
+
417
+ static void
418
+ newobj_i(VALUE tpval, void *data)
419
+ {
420
+ struct slot_logger *sl = &slot_logger;
421
+
422
+ out_tick(sl->out);
423
+ out_items(sl->out, sl->items, sl->items_types);
424
+ out_terminate(sl->out);
425
+ }
426
+
427
+ static void
428
+ start_newobj_hook(struct slot_logger *sl)
429
+ {
430
+ if (sl->hook == 0) {
431
+ sl->hook = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, NULL);
432
+ rb_gc_register_mark_object(sl->hook);
433
+ }
434
+ rb_tracepoint_enable(sl->hook);
435
+ }
436
+
437
+ static void
438
+ stop_newobj_hook(struct slot_logger *sl)
439
+ {
440
+ rb_tracepoint_disable(sl->hook);
441
+ }
442
+ static VALUE
443
+ gc_tracer_stop_slot_logging(VALUE self)
444
+ {
445
+ if (slot_logger.enabled) {
446
+ close_output(slot_logger.out);
447
+ slot_logger.out = NULL;
448
+ stop_newobj_hook(&slot_logger);
467
449
  }
468
450
  return Qnil;
469
451
  }
470
452
 
453
+ static VALUE
454
+ gc_tracer_start_slot_logging(int argc, VALUE *argv, VALUE self)
455
+ {
456
+ if (slot_logger.enabled == Qfalse) {
457
+ slot_logger.enabled = Qtrue;
458
+ slot_logger.out = open_output(argc, argv);
459
+ out_header(slot_logger.out, slot_logger.items, 0);
460
+
461
+ start_newobj_hook(&slot_logger);
462
+
463
+ if (rb_block_given_p()) {
464
+ rb_ensure(rb_yield, Qnil, gc_tracer_stop_slot_logging, Qnil);
465
+ }
466
+ }
467
+
468
+ return Qnil;
469
+ }
470
+
471
471
  #ifdef HAVE_RB_OBJSPACE_EACH_OBJECTS_WITHOUT_SETUP
472
472
  /* image logging */
473
473
 
@@ -675,7 +675,7 @@ objspace_recording_i(void *start, void *end, size_t stride, void *data)
675
675
  }
676
676
 
677
677
  static void
678
- objspace_recording(void *data, int event_index)
678
+ objspace_recording(FILE *dmy, void *data, int event_index)
679
679
  {
680
680
  /* const char *event_name = (const char *)data; */
681
681
  const char *dirname = (const char *)objspace_recorder.data;
@@ -802,6 +802,8 @@ gc_tracer_start_objspace_recording(int argc, VALUE *argv, VALUE self)
802
802
 
803
803
  #endif /* HAVE_RB_OBJSPACE_EACH_OBJECTS_WITHOUT_SETUP */
804
804
 
805
+
806
+
805
807
  /**
806
808
  * GC::Tracer traces GC/ObjectSpace behavior.
807
809
  *
@@ -829,6 +831,9 @@ Init_gc_tracer(void)
829
831
  rb_define_module_function(mod, "stop_logging", gc_tracer_stop_logging, 0);
830
832
  rb_define_module_function(mod, "setup_logging", gc_tracer_setup_logging, 1);
831
833
 
834
+ rb_define_module_function(mod, "start_slot_logging", gc_tracer_start_slot_logging, -1);
835
+ rb_define_module_function(mod, "stop_slot_logging", gc_tracer_stop_slot_logging, 0);
836
+
832
837
  /* recording methods */
833
838
  #ifdef HAVE_RB_OBJSPACE_EACH_OBJECTS_WITHOUT_SETUP
834
839
  rb_define_module_function(mod, "start_objspace_recording", gc_tracer_start_objspace_recording, -1);
@@ -851,6 +856,30 @@ Init_gc_tracer(void)
851
856
  gc_trace_items_types = rb_ary_new();
852
857
  rb_gc_register_mark_object(gc_trace_items);
853
858
  rb_gc_register_mark_object(gc_trace_items_types);
859
+ setup_items(Qnil, gc_trace_items, gc_trace_items_types);
860
+
861
+ /* slot */
862
+ slot_logger.items = rb_ary_new();
863
+ slot_logger.items_types = rb_ary_new();
864
+ rb_gc_register_mark_object(slot_logger.items);
865
+ rb_gc_register_mark_object(slot_logger.items_types);
866
+ setup_items(rb_ary_new3(4,
867
+ ID2SYM(rb_intern("count")),
868
+ ID2SYM(rb_intern("heap_live_slot")),
869
+ ID2SYM(rb_intern("heap_free_slot")),
870
+ ID2SYM(rb_intern("old_object"))),
871
+ slot_logger.items, slot_logger.items_types);
872
+ }
854
873
 
855
- gc_tracer_setup_logging(Qnil, Qnil);
874
+ #endif
875
+
876
+ #include <ruby/ruby.h>
877
+
878
+ void Init_gc_tracer_logging(VALUE m_gc_tracer); /* in gc_logging.c */
879
+
880
+ void
881
+ Init_gc_tracer(void)
882
+ {
883
+ VALUE mod = rb_define_module_under(rb_mGC, "Tracer");
884
+ Init_gc_tracer_logging(mod);
856
885
  }
@@ -1,3 +1,3 @@
1
1
  module GC::Tracer
2
- VERSION = "0.3.3"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/gc_tracer.rb CHANGED
@@ -1,3 +1,38 @@
1
1
  require "gc_tracer/version"
2
2
  require 'gc_tracer/gc_tracer'
3
3
 
4
+ module GC
5
+ module Tracer
6
+ def self.start_logging(filename_opt = nil,
7
+ filename: nil,
8
+ # event filter
9
+ events: %i(start end_mark end_sweep),
10
+ # tick type (:hw_counter, :time, :user_time, :system_time)
11
+ tick_type: :time,
12
+ # collect information
13
+ gc_stat: true,
14
+ gc_latest_gc_info: true,
15
+ rusage: false)
16
+ # setup
17
+ raise "do not specify two fienames" if filename && filename_opt
18
+ setup_logging_out(filename_opt || filename)
19
+ setup_logging_events(*events)
20
+
21
+ self.setup_logging_gc_stat = gc_stat
22
+ self.setup_logging_gc_latest_gc_info = gc_latest_gc_info
23
+ self.setup_logging_rusage = rusage
24
+ self.setup_logging_tick_type = tick_type
25
+
26
+ if block_given?
27
+ begin
28
+ start_logging_
29
+ yield
30
+ ensure
31
+ stop_logging
32
+ end
33
+ else
34
+ start_logging_
35
+ end
36
+ end
37
+ end
38
+ end
@@ -28,6 +28,7 @@ describe GC::Tracer do
28
28
  it_behaves_like "logging_test"
29
29
  end
30
30
 
31
+ =begin not supported now.
31
32
  shared_examples "objspace_recorder_test" do
32
33
  dirname = "gc_tracer_objspace_recorder_spec.#{$$}"
33
34
 
@@ -56,4 +57,5 @@ describe GC::Tracer do
56
57
  let(:count){2}
57
58
  it_behaves_like "objspace_recorder_test"
58
59
  end
60
+ =end
59
61
  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.3.3
4
+ version: 1.0.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: 2014-05-27 00:00:00.000000000 Z
11
+ date: 2014-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  version: '0'
112
112
  requirements: []
113
113
  rubyforge_project:
114
- rubygems_version: 2.2.2
114
+ rubygems_version: 2.4.5
115
115
  signing_key:
116
116
  specification_version: 4
117
117
  summary: gc_tracer gem adds GC::Tracer module.