GC::Tracer

Trace Garbage Collector activities and output statistics information.

This gem only supports MRI 2.1.0 and later.

Build Status

Installation

Add this line to your application's Gemfile:

gem 'gc_tracer'

And then execute:

$ bundle

Or install it yourself as:

$ gem install gc_tracer

Usage

gc_tracer gem adds GC::Tracer module. GC::Tracer module has the following features.

  • Logging GC statistics information
  • ObjectSpace recorder (not supported yet)

Logging

You can get GC statistics information in block form like this:

require 'gc_tracer'
GC::Tracer.start_logging(filename) do
  # do something
end

This code is equivalent to the following code.

require 'gc_tracer'
begin
  GC::Tracer.start_logging(filename)
  # do something
ensure
  GC::Tracer.stop_logging
end

If ENV['GC_TRACER_LOGFILE'] is given, then this value and pid (concatenated with '-') is used as filename.

If filename is not given, then all of logs puts onto stderr.

Setup

In the stored file (filename), you can get tab separated values of:

  • GC.stat()
  • GC.latest_gc_info()
  • getrusage() (if supported by system)
  • Custom fields (described bloew)

at each events, there are one of:

  • GC starting time (start)
  • End of marking time (end_mark)
  • End of sweeping time (end_sweep)
  • GC enter (enter)
  • GC exit (exit)
  • newobj (newobj)
  • freeobj (freeobj)

For one GC, you can get all three lines.

You can specify events by event name symbols you want to show.

require 'gc_tracer'
begin
  GC::Tracer.start_logging(filename, events: %i(enter exit))
  # do something
ensure
  GC::Tracer.stop_logging
end

Default events are "start", "end_mark" and "end_sweep". You can specify what kind of information you want to collect.

require 'gc_tracer'
begin
  GC::Tracer.start_logging(filename, gc_stat: false, gc_latest_gc_info: false, rusage: false)
  # do something
ensure
  GC::Tracer.stop_logging
end

Above example means that no details information are not needed. Default setting is "gc_stat: true, gc_latest_gc_info: true, rusage: false".

You can specify tick (time stamp) type with keyword parameter "tick_type". You can choose one of the tick type in :hw_counter, :time and :nano_time (if platform supports clock_gettime()).

See lib/gc_tracer.rb for more details.

Custom fields

You can add custom fields.

GC::Tracer.start_logging(custom_fields: [:name1, :name2, ...]) do
  # All fields are cleared by zero.

  # You can increment values of each field.
  GC::Tracer.custom_field_increment(:name1)
  # It is equivalent to
  #   GC::Tracer.custom_field_set(:name1, GC::Tracer.custom_field_get(:name1))

  # You can also decrement values
  GC::Tracer.custom_field_decrement(:name1)

  # Now, you can specify only Fixnum as field value.
  GC::Tracer.custom_field_set(:name2, 123)

  # You can specify an index instead of field name (faster than actual name)
  GC::Tracer.custom_field_increment(0) # :name1
end

Custom fields are printed as last columns.

Custom events

You can add custom events by your own. Calling GC::Tracer.custom_event_logging(event_name) in your program will puts new statistics line into the logging file.

For example, the following program insert 1000 custom event lines into logging file (stderr for this type).

GC::Tracer.start_logging(events: %i(start), gc_stat: false) do
  1_000.times{|i|
    1_000.times{''}
    GC::Tracer.custom_event_logging("custom_#{i}")
  }
end

This method is useful to trace where the GC events occur in your application.

Rack middleware

You can insert Rack middleware to record and view GC Tracer log.

require 'rack'
require 'sinatra'
require 'rack/gc_tracer'

use Rack::GCTracerMiddleware, view_page_path: '/gc_tracer'

get '/' do
  'foo'
end

You can pass two options.

  • logging_filename: File name of GC Tracer log
  • view_page_path: You can view GC tracer log with this path if logging_filename is given. You should not use this option on production.

And also you can pass all options (except filename) of GC::Tracer.start_logging.

Contributing

  1. Fork it ( http://github.com/ko1/gc_tracer/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Credit

Originally created by Koichi Sasada. Thank you Yuki Torii who helps me to make gem package.