gc_tracer 0.3.3 → 1.0.0

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