Module: GC::Tracer

Defined in:
lib/gc_tracer.rb,
lib/gc_tracer/version.rb,
ext/gc_tracer/gc_tracer.c,
ext/gc_tracer/gc_tracer.c

Constant Summary collapse

VERSION =
"1.0.0"

Class Method Summary collapse

Class Method Details

.setup_logging(ary) ⇒ Object



400
401
402
403
404
405
# File 'ext/gc_tracer/gc_tracer.c', line 400

static VALUE
gc_tracer_setup_logging(VALUE self, VALUE ary)
{
    setup_items(Qnil, gc_trace_items, gc_trace_items_types);
    return Qnil;
}

.start_logging(*args) ⇒ Object

logging methods



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'ext/gc_tracer/gc_tracer.c', line 315

def self.start_logging(filename_opt = nil,
                       filename: nil,
                       # event filter
                       events: %i(start end_mark end_sweep),
                       # tick type (:hw_counter, :time, :user_time, :system_time)
                       tick_type: :time,
                       # collect information
                       gc_stat: true,
                       gc_latest_gc_info: true,
                       rusage: false)
  # setup
  raise "do not specify two fienames" if filename && filename_opt
  setup_logging_out(filename_opt || filename)
  setup_logging_events(*events)

  self.setup_logging_gc_stat = gc_stat
  self.setup_logging_gc_latest_gc_info = gc_latest_gc_info
  self.setup_logging_rusage = rusage
  self.setup_logging_tick_type = tick_type

  if block_given?
    begin
      start_logging_
      yield
    ensure
      stop_logging
    end
  else
    start_logging_
  end
end

.start_objspace_recording(*args) ⇒ Object



738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
# File 'ext/gc_tracer/gc_tracer.c', line 738

static VALUE
gc_tracer_start_objspace_recording(int argc, VALUE *argv, VALUE self)
{
    if (objspace_recorder.enabled == Qfalse) {
	int i;
	VALUE ppmdir;
	VALUE dirname;
	VALUE picker_type = ID2SYM(rb_intern("age"));

	switch (argc) {
	  case 2:
	    picker_type = argv[1];
	  case 1:
	    dirname = argv[0];
	    break;
	  default:
	    rb_raise(rb_eArgError, "expect 1 or 2 arguments, but %d", argc);
	}

	/* setup */
	if (rb_funcall(rb_cFile, rb_intern("directory?"), 1, dirname) != Qtrue) {
	    rb_funcall(rb_cDir, rb_intern("mkdir"), 1, dirname);
	}
	if (rb_funcall(rb_cFile, rb_intern("directory?"), 1, (ppmdir = rb_str_plus(dirname, rb_str_new2("/ppm")))) != Qtrue) {
	    rb_funcall(rb_cDir, rb_intern("mkdir"), 1, ppmdir);
	}

	if (picker_type == ID2SYM(rb_intern("age"))) {
	    objspace_recorder_color_picker = object_age_picker;
	    puts_color_description(dirname, &object_age_picker_description[0], sizeof(object_age_picker_description) / sizeof(struct picker_description));
	}
	else if (picker_type == ID2SYM(rb_intern("type"))) {
	    objspace_recorder_color_picker = object_type_picker;
	    puts_color_description(dirname, &object_type_picker_description[0], sizeof(object_type_picker_description) / sizeof(struct picker_description));
	}
	else {
	    rb_raise(rb_eArgError, "unsupported picker type: %s", rb_id2name(SYM2ID(picker_type)));
	}

	HEAP_OBJ_LIMIT = FIX2INT(rb_hash_aref(
	    rb_const_get(rb_mGC, rb_intern("INTERNAL_CONSTANTS")),
	    ID2SYM(rb_intern("HEAP_OBJ_LIMIT"))));

	for (i=0; i<3; i++) {
	    objspace_recorder.funcs[i] = objspace_recording;
	    objspace_recorder.args[i]  = (void *)event_names[i];
	}

	objspace_recorder.data = ruby_xmalloc(RSTRING_LEN(dirname) + 1);
	strcpy((char *)objspace_recorder.data, RSTRING_PTR(dirname));

	create_gc_hooks(&objspace_recorder);
	start_gc_hooks(&objspace_recorder);

	if (rb_block_given_p()) {
	    rb_ensure(rb_yield, Qnil, gc_tracer_stop_objspace_recording, Qnil);
	}
    }
    else {
	rb_raise(rb_eRuntimeError, "recursive recording is not permitted");
    }

    return Qnil;
}

.start_slot_logging(*args) ⇒ Object



453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'ext/gc_tracer/gc_tracer.c', line 453

static VALUE
gc_tracer_start_slot_logging(int argc, VALUE *argv, VALUE self)
{
    if (slot_logger.enabled == Qfalse) {
	slot_logger.enabled = Qtrue;
	slot_logger.out = open_output(argc, argv);
	out_header(slot_logger.out, slot_logger.items, 0);

	start_newobj_hook(&slot_logger);

	if (rb_block_given_p()) {
	    rb_ensure(rb_yield, Qnil, gc_tracer_stop_slot_logging, Qnil);
	}
    }

    return Qnil;
}

.stop_loggingObject



303
304
305
306
307
308
309
310
311
312
313
# File 'ext/gc_tracer/gc_tracer.c', line 303

static VALUE
gc_tracer_stop_logging(VALUE self)
{
    if (logger.enabled) {
	close_output(logger.out);
	logger.out = NULL;
	stop_gc_hooks(&logger);
    }

    return Qnil;
}

.stop_objspace_recordingObject



707
708
709
710
711
712
713
714
715
# File 'ext/gc_tracer/gc_tracer.c', line 707

static VALUE
gc_tracer_stop_objspace_recording(VALUE self)
{
    if (objspace_recorder.enabled) {
	ruby_xfree(objspace_recorder.data);
	stop_gc_hooks(&objspace_recorder);
    }
    return Qnil;
}

.stop_slot_loggingObject



442
443
444
445
446
447
448
449
450
451
# File 'ext/gc_tracer/gc_tracer.c', line 442

static VALUE
gc_tracer_stop_slot_logging(VALUE self)
{
    if (slot_logger.enabled) {
	close_output(slot_logger.out);
	slot_logger.out = NULL;
	stop_newobj_hook(&slot_logger);
    }
    return Qnil;
}