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/

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

dike

Hey, ara, what’s new?

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

Hey, ara, what’s new?

touche teacher. touche.

a @ http://drawohara.com/

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

Hey, ara, what’s new?

touche teacher. touche.

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

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

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

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/