heap-profiler 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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