# README

A Gem for counting the amount of objects that have been allocated but not
released yet. Tracking this makes it easier to see if objects are being leaked
over time and if so what kind of objects. This Gem does _not_ provide any
insight into where objects are being leaked or why.

This Gem can _only_ be used on CRuby, it does not work on Rubinius due to
TracePoint not being supported on Rubinius.

## Why

The usual approach of getting object counts is by using
`ObjectSpace.each_object`. For example:

    counts = Hash.new(0)

    ObjectSpace.each_object(Object) do |obj|
      counts[obj.class] += 1
    end

Sadly this approach is rather slow (e.g. for GitLab this would take roughly
800 ms) and (seems to) force a garbage collection run after every call. In other
words, this isn't something you'd want to run in a production environment.

The allocations Gem on the other hand doesn't suffer from this problem as it
counts objects whenever they're allocated and released. This does mean that
allocating objects is slightly slower than usual, but the overhead should be
small enough to use this Gem in a production environment.

Another big difference between ObjectSpace and this Gem is that the former gives
an overview of _all_ currently retained objects whereas the allocations Gem only
tracks objects that have been allocated since it was enabled.

## Usage

Load the Gem:

    require 'allocations'

Enable it:

    Allocations.start

Getting a snapshot of the current statistics:

    Allocations.to_hash

This will return a Hash with the keys set to various classes and the values to
the amount of instances (of each class) that have not yet been released by the
garbage collector.

Disable it again and clear any existing statistics:

    Allocations.stop

## Thread Safety

The C extension uses a mutex to ensure the various methods provided by this Gem
can be used in different threads simultaneously. Each call to
`Allocations.to_hash` returns a new Hash containing a copy of the current
statistics (instead of just referring to a single global Hash).

Do note that calling `Allocation.start` and `Allocations.stop` affects _all_
running threads instead of only the current thread.

## License

All source code in this repository is subject to the terms of the MIT license,
unless stated otherwise. A copy of this license can be found the file "LICENSE".
