module MemoryProfiler

Constants

DEFAULTS

Public Class Methods

format(data) click to toggle source

Formats data, such as that returned by start , into a printable, readable string.

    # File lib/memory-profiler.rb
259 def self.format(data)
260   " Curr. Delta Class\n" +
261   " ----- ----- -----\n" +
262   data.map{|k,c,d| sprintf(" %5d %+5d %s\n", c, d, k.name) }.join
263 end
report(opt = {}) click to toggle source

Generates an instantaneous report on the current Ruby ObjectSpace, saved to a text file at: /tmp/memory_profiler-<pid>-<time>.log

Returns the filename used.

See: start for valid/default options, except that :sort_by may only have the value :current or :none when using report

    # File lib/memory-profiler.rb
112 def self.report(opt = {})
113   opt = DEFAULTS.merge(opt)
114   GC.start if opt[:force_gc]
115 
116   data = ObjectSpaceAnalyser.analyse(opt)
117 
118   if opt[:sort_by] == :current
119     data = data.to_a.sort_by{|k,v| -v }
120     data = data[0,opt[:limit]] if opt[:limit] > 0 and opt[:limit] < data.length
121   elsif opt[:sort_by] != :none
122     warn "MemoryProfiler: invalid option :sort_by => #{opt[:sort_by].inspect}; using :none"
123   end
124 
125   filename = opt[:filename] || "/tmp/memory_profiler-#{Process.pid}-#{Time.now.to_i}.log"
126   File.open(filename, 'w') do |f|
127     data.each {|k,c| f.printf( "%5d %s\n", c, k.name ) }
128   end
129 
130   GC.start if opt[:force_gc]
131   filename
132 end
restart(opt = {}) click to toggle source

Stops the current analysis, emits the results, and immediately starts a new analysis.

See: stop, start

    # File lib/memory-profiler.rb
217 def self.restart(opt = {})
218   res = self.stop
219   self.start(opt)
220   res
221 end
start(opt = {}) { || ... } click to toggle source

If a block is given, executes it and returns a summary. Otherwise, starts the analyser, and waits for a call to restart or stop.

Returned data is an array of:

[  [Class, current_usage, usage_delta],  ...  ]

Options:

:sort_by       => :current  # how to order classes;  :current | :delta | :absdelta | :none

:only          => []        # list of only classes to scan;  if empty, scans all classes
:ignore        => []        # list of classes to exclude from reports (including sub-classes and modules, but not namespaces)
:limit         => 20        # how many of the top classes to report (less than 1 means 'all'); only matters if :sort_by is not :none

:force_gc      => true      # if true, forces a garbage collection before and after generating report

:string_debug  => false     # see ObjectSpaceAnalyser#analyse
:marshal_size => false     # see ObjectSpaceAnalyser#analyse
    # File lib/memory-profiler.rb
153 def self.start(opt = {}, &block)
154   opt = DEFAULTS.merge(opt)
155   if block_given?
156     # get pre-block analysis of ObjectSpace
157     GC.start if opt[:force_gc]
158     prev = ObjectSpaceAnalyser.analyse(opt)
159     GC.start if opt[:force_gc]
160 
161     yield
162 
163     # get post-block analysis of ObjectSpace
164     GC.start if opt[:force_gc]
165     curr = ObjectSpaceAnalyser.analyse(opt)
166 
167     # calculate the differences before and after execution
168     data = self._delta(curr, prev, opt)
169 
170     # return it
171     GC.start if opt[:force_gc]
172     data
173   else
174     @@start_sync.synchronize(:EX) do
175       raise 'already started' if @@start_data
176 
177       GC.start if opt[:force_gc]
178       @@start_data = [ObjectSpaceAnalyser.analyse(opt), opt]
179       GC.start if opt[:force_gc]
180     end
181     self
182   end
183 end
start_daemon(opt = {}) click to toggle source

Begins an analysis thread that runs periodically, reporting to a text file at: /tmp/memory_profiler-<pid>.log

Returns the filename used.

Options:

:delay  => 60     # number of seconds between summaries
:filename => nil  # override the generated default

See: start for other options

   # File lib/memory-profiler.rb
60 def self.start_daemon(opt = {})
61   opt = DEFAULTS.merge(opt)
62   filename = opt[:filename] || "/tmp/memory_profiler-#{Process.pid}.log"
63   @@daemon_sync.synchronize(:EX) do
64     raise 'daemon process already running' if @@daemon_thread
65     @@daemon_thread = Thread.new do
66       prev = Hash.new(0)
67       file = File.open(filename, 'w')
68       loop do
69         begin
70           GC.start if opt[:force_gc]
71           curr = ObjectSpaceAnalyser.analyse(opt)
72           data = self._delta(curr, prev, opt)
73 
74           file.puts '-'*80
75           file.puts Time.now.to_s
76           data.each {|k,c,d| file.printf( "%5d %+5d %s\n", c, d, k.name ) }
77 
78           prev = curr
79           GC.start if opt[:force_gc]
80         rescue ::Exception => err
81           $stderr.puts "** MemoryProfiler daemon error: #{err}", err.backtrace.map{|b| "\t#{b}" }
82         end
83         sleep opt[:delay]
84       end #loop
85     end #Thread.new
86   end
87   filename
88 end
stop() click to toggle source

Stops the current analysis and emits the results.

See: start

    # File lib/memory-profiler.rb
190 def self.stop
191   prev = nil
192   opt  = nil
193   @@start_sync.synchronize(:EX) do
194     raise 'not started' unless @@start_data
195     prev, opt = @@start_data
196     @@start_data = nil
197   end
198 
199   # get the current state of affairs
200   GC.start if opt[:force_gc]
201   curr = ObjectSpaceAnalyser.analyse(opt)
202 
203   # calculate the differences before and after execution
204   data = self._delta(curr, prev, opt)
205 
206   # return it
207   GC.start if opt[:force_gc]
208   data
209 end
stop_daemon() click to toggle source

Terminates the analysis thread started by start_daemon

    # File lib/memory-profiler.rb
 93 def self.stop_daemon
 94   @@daemon_sync.synchronize(:EX) do
 95     raise 'no daemon process running' unless @@daemon_thread
 96     @@daemon_thread.kill
 97     @@daemon_thread.join
 98     @@daemon_thread = nil
 99   end
100   self
101 end