Class: MemKit::Profiler
- Inherits:
-
Object
- Object
- MemKit::Profiler
- Defined in:
- lib/mem_kit/profiler.rb
Class Method Summary collapse
- .collect(limit: nil) ⇒ Object
- .format_percentage(value, total) ⇒ Object
- .format_size(bytes) ⇒ Object
- .is_running ⇒ Object
- .start(logger: nil, interval: 120, limit: nil) ⇒ Object
- .stop ⇒ Object
- .update_object(object, result, total_memory_size) ⇒ Object
Class Method Details
.collect(limit: nil) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/mem_kit/profiler.rb', line 50 def self.collect(limit: nil) @rvalue_size ||= GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] total_memory_size = ObjectSpace.memsize_of_all result = { total_memory_usage: format_size(total_memory_size), total_allocations: ObjectSpace.each_object{}, symbol_count: Symbol.all_symbols.size, object_counts: ObjectSpace.count_objects, objects: [] } ObjectSpace.each_object do |o| update_object(o, result, total_memory_size) end result[:objects].sort! { |a,b| b[:bytes] <=> a[:bytes] } if limit != nil result[:objects] = result[:objects][0, limit] end return result end |
.format_percentage(value, total) ⇒ Object
111 112 113 |
# File 'lib/mem_kit/profiler.rb', line 111 def self.format_percentage(value, total) return "#{(value.to_f / total.to_f * 100.0).round(2)}%" end |
.format_size(bytes) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/mem_kit/profiler.rb', line 79 def self.format_size(bytes) value = bytes unit = 'Bytes' if bytes >= 100000 #format as MB value = (bytes.to_f / 1000.0 / 1000.0).round(2) unit = 'MB' elsif bytes >= 500 #format as KB value = (bytes.to_f / 1000.0).round(2) unit = 'KB' end return "#{value} #{unit}" end |
.is_running ⇒ Object
6 7 8 |
# File 'lib/mem_kit/profiler.rb', line 6 def self.is_running return @is_running end |
.start(logger: nil, interval: 120, limit: nil) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/mem_kit/profiler.rb', line 10 def self.start(logger: nil, interval: 120, limit: nil) if logger == nil logger = Logger.new(STDOUT) end logger.debug("[MemKit::Profiler] - Starting Memory Profiling. Interval: #{interval} seconds | Limit: #{limit || 'N/A'}.") %w'INT TERM'.each do |sig| Signal.trap(sig) { stop } end if @is_running == true raise "[MemKit::Profiler] - Profiler is already running." end @is_running = true @thread = Thread.new do while @is_running == true do GC.start result = collect(limit: limit) logger.debug("[MemKit::Profiler}] - #{JSON.dump(result)}") sleep(interval) end end return @thread end |
.stop ⇒ Object
72 73 74 75 76 77 |
# File 'lib/mem_kit/profiler.rb', line 72 def self.stop @is_running = false if @thread != nil Thread.kill(@thread) end end |
.update_object(object, result, total_memory_size) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/mem_kit/profiler.rb', line 94 def self.update_object(object, result, total_memory_size) obj = result[:objects].detect { |o| o[:klass] == object.class } if obj == nil mem_usage = ObjectSpace.memsize_of(object) + @rvalue_size # compensate for API bug mem_usage = @rvalue_size if mem_usage > 100_000_000_000 obj = { klass: object.class, allocation_count: 1, memory_usage_size: format_size(mem_usage), memory_usage_percentage: format_percentage(mem_usage, total_memory_size), bytes: mem_usage } result[:objects].push(obj) else obj[:allocation_count] += 1 obj[:bytes] += ObjectSpace.memsize_of(object) obj[:memory_usage_size] = format_size(obj[:bytes]) obj[:memory_usage_percentage] = format_percentage(obj[:bytes], total_memory_size) end return obj end |