diff options
Diffstat (limited to '')
-rwxr-xr-x | storage/mroonga/vendor/groonga/tools/groonga-memory-usage-analyzer.rb | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/storage/mroonga/vendor/groonga/tools/groonga-memory-usage-analyzer.rb b/storage/mroonga/vendor/groonga/tools/groonga-memory-usage-analyzer.rb new file mode 100755 index 00000000..5c4d5669 --- /dev/null +++ b/storage/mroonga/vendor/groonga/tools/groonga-memory-usage-analyzer.rb @@ -0,0 +1,127 @@ +#!/usr/bin/env ruby + +class Memory < Struct.new(:size, :file, :line, :function) + def location + "#{file}:#{line}" + end +end + +class LocationGroup + attr_reader :location + attr_reader :memories + def initialize(location) + @location = location + @memories = [] + end + + def add(memory) + @memories << memory + end + + def total_size + @memories.inject(0) do |sum, memory| + sum + memory.size + end + end + + def average_size + total_size / @memories.size.to_f + end + + def max_size + @memories.collect(&:size).max + end + + def min_size + @memories.collect(&:size).min + end +end + +class Statistics + def initialize + @location_groups = {} + end + + def add(memory) + group = location_group(memory.location) + group.add(memory) + end + + def sort_by_size + @location_groups.values.sort_by do |group| + group.total_size + end + end + + private + def location_group(location) + @location_groups[location] ||= LocationGroup.new(location) + end +end + +statistics = Statistics.new + +ARGF.each_line do |line| + case line + when /\Aaddress\[\d+\]\[not-freed\]:\s + (?:0x)?[\da-fA-F]+\((\d+)\):\s + (.+?):(\d+):\s(\S+)/x + size = $1.to_i + file = $2 + line = $3.to_i + function = $4.strip + memory = Memory.new(size, file, line, function) + statistics.add(memory) + end +end + +def format_size(size) + if size < 1024 + "#{size}B" + elsif size < (1024 * 1024) + "%.3fKiB" % (size / 1024.0) + elsif size < (1024 * 1024 * 1024) + "%.3fMiB" % (size / 1024.0 / 1024.0) + elsif size < (1024 * 1024 * 1024 * 1024) + "%.3fGiB" % (size / 1024.0 / 1024.0 / 1024.0) + else + "#{size}B" + end +end + +puts("%10s(%10s:%10s:%10s): %s(%s)" % [ + "Total", + "Average", + "Max", + "Min", + "Location", + "N allocations", + ]) +top_allocated_groups = statistics.sort_by_size.reverse_each.take(10) +top_allocated_groups.each do |group| + puts("%10s(%10s:%10s:%10s): %s(%d)" % [ + format_size(group.total_size), + format_size(group.average_size), + format_size(group.max_size), + format_size(group.min_size), + group.location, + group.memories.size, + ]) +end + +puts +puts("Top allocated location's details") +top_allocated_group = top_allocated_groups.first +target_memories = top_allocated_group.memories +size_width = Math.log10(target_memories.size).floor + 1 +target_memories.group_by(&:size).sort_by do |size, memories| + size * memories.size +end.reverse_each do |size, memories| + total_size = memories.inject(0) {|sum, memory| sum + memory.size} + puts("%10s(%10s * %#{size_width}d): %s" % [ + format_size(total_size), + format_size(size), + memories.size, + memories.first.location, + ]) +end |