def initialize(file)
@entries = []
@num_requests = 0
@topology = []
@object_types = Set.new
@mallocs = @malloced = @leaks = @leaked = 0
file.each_line do |line|
case line
when /^Garbage collection started$/
@entries << GCLogEntry.new
when /^objects processed\s*:\s*(\d+)$/
@entries.last.processed = $1.to_i
when /^live objects\s*:\s*(\d+)$/
@entries.last.live = $1.to_i
when /^freelist objects\s*:\s*(\d+)$/
@entries.last.freelist = $1.to_i
when /^freed objects\s*:\s*(\d+)$/
@entries.last.freed = $1.to_i
when /^GC time\s*:\s*(\d+)\s*msec$/
@entries.last.time = $1.to_i
when /^number of requests processed: (\d+)$/
@num_requests = $1.to_i
when /^HEAP\[\s*(\d+)\]: size=\s*(\d+)$/
@topology = [] if $1.to_i == 0
@topology << $2.to_i
when /^kept (\d+) \/ freed (\d+) objects of type ([a-zA-Z]+)/
@object_types.add($3)
@entries.last.live_objects[$3] = $1.to_i
@entries.last.freed_objects[$3] = $2.to_i
when /^(\d+) nodes malloced for (\d+) KB$/
@mallocs = $1.to_i
@malloced = $2.to_i * 1024
when /^(\d+) leaks for (\d+) total leaked bytes.$/
@leaks = $1.to_i
@leaked = $2.to_i
end
end
@time_total = @entries.map{|e| e.time}.sum
@collections = @entries.length
@garbage_produced = @entries.map{|e| e.freed}.sum
@live_objects = @entries.map{|e| e.live_objects}
@freed_objects = @entries.map{|e| e.freed_objects}
@freelist = @entries.map{|e| e.freelist}
@garbage_totals = @freed_objects.inject(Hash.new(0)) do |totals, freed|
freed.each do |object_type, count|
totals[object_type] += freed[object_type] || 0
end
totals
end
GCAttributes.each do |attr|
a = @entries.map{|e| e.send attr}
a.pop if :freelist == attr.to_sym
[:min, :max, :mean].each do |method|
instance_variable_set "@#{attr}_#{method}", (a.send method)
end
mean = instance_variable_get "@#{attr}_mean"
stddev = instance_variable_set "@#{attr}_stddev", (a.send :stddev, mean)
instance_variable_set "@#{attr}_stddev_percentage", stddev_percentage(stddev, mean)
end
end