heap-profiler 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,9 +11,6 @@ module HeapProfiler
11
11
 
12
12
  def process(_index, object)
13
13
  @objects += 1
14
- unless object[:memsize]
15
- p object
16
- end
17
14
  @memory += object[:memsize]
18
15
  end
19
16
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'optparse'
2
3
 
3
4
  module HeapProfiler
4
5
  class CLI
@@ -7,13 +8,21 @@ module HeapProfiler
7
8
  end
8
9
 
9
10
  def run
10
- if @argv.size == 1
11
- print_report(@argv.first)
12
- 0
13
- else
14
- print_usage
15
- 1
11
+ parser.parse!(@argv)
12
+
13
+ begin
14
+ if @argv.size == 1
15
+ print_report(@argv.first)
16
+ return 0
17
+ end
18
+ rescue CapacityError => error
19
+ STDERR.puts(error.message)
20
+ STDERR.puts("Current size: #{Parser.batch_size}B")
21
+ STDERR.puts("Try increasing it with --batch-size")
22
+ STDERR.puts
16
23
  end
24
+ print_usage
25
+ 1
17
26
  end
18
27
 
19
28
  def print_report(path)
@@ -28,5 +37,51 @@ module HeapProfiler
28
37
  def print_usage
29
38
  puts "Usage: #{$PROGRAM_NAME} directory_or_heap_dump"
30
39
  end
40
+
41
+ SIZE_UNITS = {
42
+ 'B' => 1,
43
+ 'K' => 1_000,
44
+ 'M' => 1_000_000,
45
+ 'G' => 1_000_000_000,
46
+ }
47
+ def parse_byte_size(size_string)
48
+ if (match = size_string.match(/\A(\d+)(\w)?B?\z/i))
49
+ digits = Float(match[1])
50
+ base = 1
51
+ unit = match[2]&.upcase
52
+ if unit
53
+ base = SIZE_UNITS.fetch(unit) { raise ArgumentError, "Unknown size unit: #{unit}" }
54
+ end
55
+ size = (digits * base).to_i
56
+ if size > 4_000_000_000
57
+ raise ArgumentError, "Batch size can't be bigger than 4G"
58
+ end
59
+ size
60
+ else
61
+ raise ArgumentError, "#{size_string} is not a valid size"
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def parser
68
+ @parser ||= OptionParser.new do |opts|
69
+ opts.banner = "Usage: heap-profiler [ARGS]"
70
+ opts.separator ""
71
+ opts.separator "GLOBAL OPTIONS"
72
+ opts.separator ""
73
+
74
+ help = <<~EOS
75
+ Sets the simdjson parser batch size. It must be larger than the largest JSON document in the
76
+ heap dump, and defaults to 10MB.
77
+ EOS
78
+ opts.on('--batch-size SIZE', help.strip) do |size_string|
79
+ HeapProfiler::Parser.batch_size = parse_byte_size(size_string)
80
+ rescue ArgumentError => error
81
+ STDERR.puts "Invalid batch-size: #{error.message}"
82
+ exit 1
83
+ end
84
+ end
85
+ end
31
86
  end
32
87
  end
@@ -62,7 +62,7 @@ module HeapProfiler
62
62
  end
63
63
 
64
64
  def each_object(since: nil, &block)
65
- Parser.load_many(path, since: since, batch_size: 10_000_000, &block)
65
+ Parser.load_many(path, since: since, &block)
66
66
  end
67
67
 
68
68
  def stats
@@ -4,6 +4,11 @@ module HeapProfiler
4
4
  module Parser
5
5
  CLASS_DEFAULT_PROC = ->(_hash, key) { "<Class#0x#{key.to_s(16)}>" }
6
6
 
7
+ class << self
8
+ attr_accessor :batch_size
9
+ end
10
+ self.batch_size = 10_000_000 # 10MB
11
+
7
12
  class Ruby
8
13
  def build_index(path)
9
14
  require 'json'
@@ -42,15 +47,13 @@ module HeapProfiler
42
47
  end
43
48
 
44
49
  class Native
45
- DEFAULT_BATCH_SIZE = 10_000_000 # 10MB
46
-
47
- def build_index(path, batch_size: DEFAULT_BATCH_SIZE)
50
+ def build_index(path, batch_size: Parser.batch_size)
48
51
  indexes = _build_index(path, batch_size)
49
52
  indexes.first.default_proc = CLASS_DEFAULT_PROC
50
53
  indexes
51
54
  end
52
55
 
53
- def load_many(path, since: nil, batch_size: DEFAULT_BATCH_SIZE, &block)
56
+ def load_many(path, since: nil, batch_size: Parser.batch_size, &block)
54
57
  _load_many(path, since, batch_size, &block)
55
58
  end
56
59
  end
@@ -8,6 +8,7 @@ require "heap_profiler/reporter"
8
8
 
9
9
  module HeapProfiler
10
10
  Error = Class.new(StandardError)
11
+ CapacityError = Class.new(Error)
11
12
 
12
13
  class << self
13
14
  attr_accessor :current_reporter
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module HeapProfiler
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heap-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-26 00:00:00.000000000 Z
11
+ date: 2021-01-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Make several heap dumps and summarize allocated, retained memory
14
14
  email:
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  requirements: []
82
- rubygems_version: 3.1.4
82
+ rubygems_version: 3.2.5
83
83
  signing_key:
84
84
  specification_version: 4
85
85
  summary: Ruby heap profiling tool