NAME

dike

SYNOPSIS

a simple memory leak detector for ruby with preconfigured rails hooks.

INSTALL

gem install dike

URIS

http://www.codeforpeople.com/lib/ruby/
http://rubyforge.org/projects/codeforpeople/

DESCRIPTION

the concept behind dike.rb is simple: class Object is extended in order that
the location of each object's creation is tracked.  a summarizer command is
given to walk ObjectSpace using each object's class and the location if it's
creation to detect memory leaks.  not all leaks can be detected and some that
are may not really be leaks, but dike provided a simple way to see the
hotspots in your code that may potentially be leaking.

EXAMPLES

PURE RUBY

  require 'dike'

  Dike.log STDERR # the default

  Thread.new do
    sleep 4.2 and Dike.finger
  end

  Main.start

RAILS

  file:RAILS_ROOT/config/environment.rb
    ...
    require 'dike'

  shell: ./script/server

  shell: curl --silent http://localhost:3000 >/dev/null

  shell: cat ./log/dike/0
  ---
  - class: String
    count: 90769
    trace: []
  - class: Array
    count: 18931
    trace: []
  - class: Class
    count: 2
    trace:
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:222:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `each'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:248:in `Widget'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets/page/base.rb:1
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `require'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `load'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:16:in `for_controller'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:243:in `widget'
    - /Users/ahoward/site/votelink.com/public/../config/../app/controllers/application.rb:150
  ...

  shell: curl --silent http://localhost:3000 >/dev/null

  shell: cat ./log/dike/1
  ---
  - class: String
    count: 100769
    trace: []
  - class: Array
    count: 19931
    trace: []
  - class: Class
    count: 5
    trace:
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:222:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `each'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:248:in `Widget'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets/page/base.rb:1
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `require'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `load'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:16:in `for_controller'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:243:in `widget'
    - /Users/ahoward/site/votelink.com/public/../config/../app/controllers/application.rb:150
  ...

  shell: dike ./log/dike
  ...
  - class: Class
    count: 3
    trace:
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:222:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `each'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `class_factory'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:248:in `Widget'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets/page/base.rb:1
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `require'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `load'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:16:in `for_controller'
    - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:243:in `widget'
    - /Users/ahoward/site/votelink.com/public/../config/../app/controllers/application.rb:150
  ...

SUMMARY

* the 'Dike.finger' method dumps it's log in a format showing

  class : the class of object being leaked/allocated
  count : the number instances leaked from the trace location
  trace : the trace location of object creation

* loading into a rails environment causes snapshots of the above format to
  be dumped into RAILS_ROOT/log/dike/ after each request.  each snapshot is
  incrementally numbered 0, 1, ...

* the 'dike' command line tool can be used in two ways

    dike directory/with/logs/dike/

    dike old_dump new_dump

  if given a directory 'old_dump' and 'new_dump' are auto-calculated by
  scanning the directory.  in either case the tool dups a delta running old
  -->> new.  the delta shows only changes from old to new, so a line like

    - class: Proc
      count: 3 
      ...

  means that 3 Proc objects were created between the two dumps.  note that,
  when given a directory, the default old and new dumps are the oldest and
  newest dumps respectively, to get fine grained information sumarizing the
  changes between two requests give the files manually, for example

    dike ./log/dike/41 ./log/dike/42

* options that affect logging

  - Dike.filter pattern

      pattern must respond to '===' and each object in ObjectSpace will be
      compared against it.  for example

        Dile.filter Array

      would cause logging to restrict itself to Array, or sublcasses of
      Array

  - Dike.log io

      set the dike logging object.  the object should respond to 'puts'.

  - Dike.logfactory directory

      cause logging to occur into a new log for each call the 'Dike.finger'.
      the logs will be auto numbered 0, 1, ...

LIMITATIONS

not all object creation can be tracked and not all leaks are reported.

AUTHOR

ara [dot] t [dot] howard [at] gmail [dot] com