[ANN] dike-0.0.3

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

    ## just dumping sequential snapshots to stderr

     # cfp:~ > cat sample/a.rb
         require 'dike'

         Leaks = Array.new

         loop do
           Leaks << String.new('leak' * 1024)
           Dike.finger
           sleep 1
         end

     # cfp:~ > ruby sample/a.rb | less
         ...

         - class: String
           count: 2
           trace:
           - sample/a.rb:6
           - sample/a.rb:5:in `loop'
           - sample/a.rb:5

         ...

         - class: String
           count: 10
           trace:
           - sample/a.rb:6
           - sample/a.rb:5:in `loop'
           - sample/a.rb:5

         ...

         - class: String
           count: 42
           trace:
           - sample/a.rb:6
           - sample/a.rb:5:in `loop'
           - sample/a.rb:5

    ## dumping sequential snapshots using Dike.logfactory and then using the 'dike'
       command line tool to do comparisons of the dumped snapshots

     # cfp:~ > cat sample/b.rb
         require 'dike'

         Leaks = Array.new

         class Leak
           def initialize
             @leak = 42.chr * (2 ** 20)
           end
         end

         Dike.logfactory './log/'

         Dike.finger

         3.times{ Leaks << Leak.new }

         Dike.finger

         2.times{ Leaks << Leak.new }

         Dike.finger

     # cfp:~ > ruby sample/b.rb

     # cfp:~ > ls log/
         0 1 2

     # cfp:~ > dike log/

···

---
         - class: Leak
           count: 3
           trace:
           - sample/b.rb:15
           - sample/b.rb:15:in `times'
           - sample/b.rb:15
         - class: Leak
           count: 2
           trace:
           - sample/b.rb:19
           - sample/b.rb:19:in `times'
           - sample/b.rb:19

     # cfp:~ > dike log/0 log/1
         ---
         - class: Leak
           count: 3
           trace:
           - sample/b.rb:15
           - sample/b.rb:15:in `times'
           - sample/b.rb:15

     # cfp:~ > dike log/1 log/2
         ---
         - class: Leak
           count: 2
           trace:
           - sample/b.rb:19
           - sample/b.rb:19:in `times'
           - sample/b.rb:19

   ### RAILS

     # cfp:~ > cat ./config/environment.rb
       ...
       require 'dike'
       Dike.on :rails

     # cfp:~ > ./script/server

     # cfp:~ > curl --silent http://localhost:3000 >/dev/null

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

     # cfp:~ > curl --silent http://localhost:3000 >/dev/null

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

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

NOTES

   * 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. not all leaks are reported. some
   reported leaks are not. dike shows you where in the source objects are being
   created that cannot be reclaimed - these are not always leaks as this line

     class C; end

   shows. the class 'C' cannot be reclaimed and is not a leak.

AUTHOR

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

enjoy.

a @ http://drawohara.com/
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Hey, ara, what's new?

···

On Sun, 30 Sep 2007 03:43:32 +0900, ara.t.howard wrote:

   dike

--
Jay Levitt |
Boston, MA | My character doesn't like it when they
Faster: jay at jay dot fm | cry or shout or hit.
http://www.jay.fm | - Kristoffer

touche teacher. touche.

a @ http://drawohara.com/

···

On Sep 30, 2007, at 7:25 PM, Jay Levitt wrote:

Hey, ara, what's new?

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

No, I mean, really.. what's new? There's no changelog.

···

On Mon, 1 Oct 2007 11:58:30 +0900, ara.t.howard wrote:

Hey, ara, what's new?

touche teacher. touche.

--
Jay Levitt |
Boston, MA | My character doesn't like it when they
Faster: jay at jay dot fm | cry or shout or hit.
http://www.jay.fm | - Kristoffer

sorry.

  - few small bug fixes, nothing functional though

  - made installation into rails require

     Dike.on :rails

and i thought you were being so clever.

cheers.

a @ http://drawohara.com/

···

On Sep 30, 2007, at 9:55 PM, Jay Levitt wrote:

No, I mean, really.. what's new? There's no changelog.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama