add some memory logging support
[opensuse:software-o-o.git] / lib / memory_profiler.rb
1 class MemoryProfiler
2   DEFAULTS = {:delay => 10, :string_debug => false}
3
4   def self.start(opt={})
5     opt = DEFAULTS.dup.merge(opt)
6
7     Thread.new do
8       prev = Hash.new(0)
9       curr = Hash.new(0)
10       curr_strings = []
11       delta = Hash.new(0)
12
13       file = File.open('log/memory_profiler.log','w')
14
15       loop do
16         begin
17           GC.start
18           curr.clear
19
20           curr_strings = [] if opt[:string_debug]
21
22           ObjectSpace.each_object do |o|
23             curr[o.class] += 1 #Marshal.dump(o).size rescue 1
24             if opt[:string_debug] and o.class == String
25               curr_strings.push o
26             end
27           end
28
29           if opt[:string_debug]
30             File.open("log/memory_profiler_strings.log.#{Time.now.to_i}",'w') do |f|
31               curr_strings.sort.each do |s|
32                 f.puts s
33               end
34             end
35             curr_strings.clear
36           end
37
38           delta.clear
39           (curr.keys + delta.keys).uniq.each do |k,v|
40             delta[k] = curr[k]-prev[k]
41           end
42
43           file.puts "Top 20"
44           delta.sort_by { |k,v| -v.abs }[0..19].sort_by { |k,v| -v}.each do |k,v|
45             file.printf "%+5d: %s (%d)\n", v, k.name, curr[k] unless v == 0
46           end
47           file.flush
48
49           delta.clear
50           prev.clear
51           prev.update curr
52           GC.start
53         rescue Exception => err
54           STDERR.puts "** memory_profiler error: #{err}"
55         end
56         sleep opt[:delay]
57       end
58     end
59   end
60 end