memory_profiler 1.0.0 → 1.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dea36221189a4ea796d262870a9a09acf48fcfe3b6321814fc3e86cc1f4c37db
4
- data.tar.gz: '059ab396fc3c0e928046dd3f5c0e6271a616a369f427ee8d134521bb934e8cd8'
3
+ metadata.gz: e4c8c5a12cd11ab3f9c5ab852e6bca0cb442ccc25f54997f49243a19aa6cef9b
4
+ data.tar.gz: 5c0ca217ca3cbc0edca725071512688443ac24a5d3e9f28980d93d3dd30a323f
5
5
  SHA512:
6
- metadata.gz: 69a830fb9ac126817342cc84e70f0796417d119ae337172a6b79a26d10e78a08146a4496915c384c7f993e8c514d43168e8e9d1d925acb856ca77092bdd1535e
7
- data.tar.gz: 6de39e21847f551fac3b53107e5fa9d8cba5c6d00cfd39fb104432bc44f83008afefe9c46138ce4560e91880f245456b00f60718593198d735a379e4d93b8d71
6
+ metadata.gz: 11d3bf57b920c915a0a98f6cea8798349983b0c64047f481ab1227301ff100a8de16f858ee7d21028d32e3dd04015446f77555bfd050755637714da5d1cc08b3
7
+ data.tar.gz: 46d2df335163a6ddc35ea3a0eff97573dc7b8a50d671e9aa8940a5acb300ea342d7eb38e10f03f39f3705c4e9ed318a336c68f72ddf39a5cdf4f6bb81b9cc7e5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1 - 23-10-2022
4
+
5
+ - Adapts tests to Ruby 3.0 / 3.1
6
+ - Lazy report evaluation
7
+ - Tested under Truffle Ruby
8
+
3
9
  ## 1.0.0 - 02-12-2020
4
10
 
5
11
  - Added new CLI `ruby-memory-profiler` which can be used to profile scripts @fatkodima
data/README.md CHANGED
@@ -112,7 +112,7 @@ The `pretty_print` method can take a few options:
112
112
  * `to_file`: a path to your log file - can be given a String
113
113
  * `color_output`: a flag for whether to colorize output - can be given a Boolean
114
114
  * `retained_strings`: how many retained strings to print - can be given an Integer
115
- * `allocated_strings`: how many allocated strings to print - can be given a String
115
+ * `allocated_strings`: how many allocated strings to print - can be given a Integer
116
116
  * `detailed_report`: should report include detailed information - can be given a Boolean
117
117
  * `scale_bytes`: flag to convert byte units (e.g. 183200000 is reported as 183.2 MB, rounds with a precision of 2 decimal digits) - can be given a Boolean
118
118
  * `normalize_paths`: flag to remove a gem's directory path from printed locations - can be given a Boolean
@@ -16,7 +16,7 @@ module MemoryProfiler
16
16
  gemname
17
17
  elsif /\/rubygems[\.\/]/ =~ path
18
18
  "rubygems"
19
- elsif /ruby\/2\.[^\/]+\/(?<stdlib>[^\/\.]+)/ =~ path
19
+ elsif /ruby\/\d\.[^\/]+\/(?<stdlib>[^\/\.]+)/ =~ path
20
20
  stdlib
21
21
  elsif /(?<app>[^\/]+\/(bin|app|lib))/ =~ path
22
22
  app
@@ -34,8 +34,7 @@ module MemoryProfiler
34
34
  end
35
35
 
36
36
  def start
37
- GC.start
38
- GC.start
37
+ 3.times { GC.start }
39
38
  GC.start
40
39
  GC.disable
41
40
 
@@ -49,8 +48,11 @@ module MemoryProfiler
49
48
  retained = StatHash.new.compare_by_identity
50
49
 
51
50
  GC.enable
52
- GC.start
53
- GC.start
51
+ # for whatever reason doing GC in a block is more effective at
52
+ # freeing objects.
53
+ # full_mark: true, immediate_mark: true, immediate_sweep: true are already default
54
+ 3.times { GC.start }
55
+ # another start outside of the block to release the block
54
56
  GC.start
55
57
 
56
58
  # Caution: Do not allocate any new Objects between the call to GC.start and the completion of the retained
@@ -86,8 +88,6 @@ module MemoryProfiler
86
88
  # Iterates through objects in memory of a given generation.
87
89
  # Stores results along with meta data of objects collected.
88
90
  def object_list(generation)
89
-
90
- rvalue_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
91
91
  helper = Helpers.new
92
92
 
93
93
  result = StatHash.new.compare_by_identity
@@ -114,7 +114,7 @@ module MemoryProfiler
114
114
  string = klass == String ? helper.lookup_string(obj) : nil
115
115
 
116
116
  # compensate for API bug
117
- memsize = rvalue_size if memsize > 100_000_000_000
117
+ memsize = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] if memsize > 100_000_000_000
118
118
  result[obj.__id__] = MemoryProfiler::Stat.new(class_name, gem, file, location, memsize, string)
119
119
  rescue
120
120
  # give up if any any error occurs inspecting the object
@@ -24,7 +24,16 @@ module MemoryProfiler
24
24
 
25
25
  TYPES.each do |type|
26
26
  METRICS.each do |metric|
27
- attr_accessor "#{type}_#{metric}_by_#{name}"
27
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
28
+ def #{type}_#{metric}_by_#{name} # def allocated_memory_by_file
29
+ @#{type}_#{metric}_by ||= {} # @allocated_memory_by ||= {}
30
+ #
31
+ @#{type}_#{metric}_by['#{name}'] ||= begin # @allocated_memory_by['file'] ||= begin
32
+ _, stat_attribute = @@lookups.find { |(n, _stat_attribute)| n == '#{name}' } # _, stat_attribute = @@lookups.find { |(n, _stat_attribute)| n == 'file' }
33
+ @#{type}.top_n_#{metric}(@top, stat_attribute) # @allocated.top_n_memory(@top, stat_attribute)
34
+ end # end
35
+ end # end
36
+ RUBY
28
37
  end
29
38
  end
30
39
  end
@@ -34,27 +43,20 @@ module MemoryProfiler
34
43
  register_type 'location', :location
35
44
  register_type 'class', :class_name
36
45
 
37
- attr_accessor :strings_retained, :strings_allocated
46
+ attr_writer :strings_retained, :strings_allocated
38
47
  attr_accessor :total_retained, :total_allocated
39
48
  attr_accessor :total_retained_memsize, :total_allocated_memsize
40
49
 
41
- def register_results(allocated, retained, top)
42
-
43
- @@lookups.each do |name, stat_attribute|
44
-
45
- memsize_results, count_results = allocated.top_n(top, stat_attribute)
46
-
47
- self.send("allocated_memory_by_#{name}=", memsize_results)
48
- self.send("allocated_objects_by_#{name}=", count_results)
49
-
50
- memsize_results, count_results = retained.top_n(top, stat_attribute)
51
-
52
- self.send("retained_memory_by_#{name}=", memsize_results)
53
- self.send("retained_objects_by_#{name}=", count_results)
54
- end
50
+ def initialize
51
+ @allocated = StatHash.new
52
+ @retained = StatHash.new
53
+ @top = 50
54
+ end
55
55
 
56
- self.strings_allocated = string_report(allocated, top)
57
- self.strings_retained = string_report(retained, top)
56
+ def register_results(allocated, retained, top)
57
+ @allocated = allocated
58
+ @retained = retained
59
+ @top = top
58
60
 
59
61
  self.total_allocated = allocated.size
60
62
  self.total_allocated_memsize = total_memsize(allocated)
@@ -64,6 +66,14 @@ module MemoryProfiler
64
66
  self
65
67
  end
66
68
 
69
+ def strings_allocated
70
+ @strings_allocated ||= string_report(@allocated, @top)
71
+ end
72
+
73
+ def strings_retained
74
+ @strings_retained ||= string_report(@retained, @top)
75
+ end
76
+
67
77
  def scale_bytes(bytes)
68
78
  return "0 B" if bytes.zero?
69
79
 
@@ -139,10 +149,10 @@ module MemoryProfiler
139
149
  end
140
150
  end
141
151
  end
142
- end
143
152
 
144
- io.puts
145
- print_string_reports(io, options)
153
+ io.puts
154
+ print_string_reports(io, options)
155
+ end
146
156
 
147
157
  io.close if io.is_a? File
148
158
  end
@@ -162,7 +172,7 @@ module MemoryProfiler
162
172
  @normalize_path[path] ||= begin
163
173
  if %r!(/gems/.*)*/gems/(?<gemname>[^/]+)(?<rest>.*)! =~ path
164
174
  "#{gemname}#{rest}"
165
- elsif %r!ruby/2\.[^/]+/(?<stdlib>[^/.]+)(?<rest>.*)! =~ path
175
+ elsif %r!ruby/\d\.[^/]+/(?<stdlib>[^/.]+)(?<rest>.*)! =~ path
166
176
  "ruby/lib/#{stdlib}#{rest}"
167
177
  elsif %r!(?<app>[^/]+/(bin|app|lib))(?<rest>.*)! =~ path
168
178
  "#{app}#{rest}"
@@ -5,32 +5,40 @@ module MemoryProfiler
5
5
  # Fast approach for determining the top_n entries in a Hash of Stat objects.
6
6
  # Returns results for both memory (memsize summed) and objects allocated (count) as a tuple.
7
7
  def top_n(max, metric_method)
8
+ [
9
+ top_n_memory(max, metric_method),
10
+ top_n_objects(max, metric_method)
11
+ ]
12
+ end
8
13
 
14
+ def top_n_memory(max, metric_method)
9
15
  metric_memsize = Hash.new(0)
10
- metric_objects_count = Hash.new(0)
11
16
 
12
17
  each_value do |value|
13
18
  metric = value.send(metric_method)
14
-
15
19
  metric_memsize[metric] += value.memsize
16
- metric_objects_count[metric] += 1
17
20
  end
18
21
 
19
- stats_by_memsize =
20
- metric_memsize
21
- .to_a
22
- .sort_by! { |metric, memsize| [-memsize, metric] }
23
- .take(max)
24
- .map! { |metric, memsize| { data: metric, count: memsize } }
22
+ metric_memsize
23
+ .to_a
24
+ .sort_by! { |metric, memsize| [-memsize, metric] }
25
+ .take(max)
26
+ .map! { |metric, memsize| { data: metric, count: memsize } }
27
+ end
25
28
 
26
- stats_by_count =
27
- metric_objects_count
28
- .to_a
29
- .sort_by! { |metric, count| [-count, metric] }
30
- .take(max)
31
- .map! { |metric, count| { data: metric, count: count } }
29
+ def top_n_objects(max, metric_method)
30
+ metric_objects_count = Hash.new(0)
31
+
32
+ each_value do |value|
33
+ metric = value.send(metric_method)
34
+ metric_objects_count[metric] += 1
35
+ end
32
36
 
33
- [stats_by_memsize, stats_by_count]
37
+ metric_objects_count
38
+ .to_a
39
+ .sort_by! { |metric, count| [-count, metric] }
40
+ .take(max)
41
+ .map! { |metric, count| { data: metric, count: count } }
34
42
  end
35
43
  end
36
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MemoryProfiler
4
- VERSION = "1.0.0"
4
+ VERSION = "1.0.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memory_profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-01 00:00:00.000000000 Z
11
+ date: 2022-10-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Memory profiling routines for Ruby 2.5+
14
14
  email:
@@ -52,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  requirements: []
55
- rubygems_version: 3.1.4
55
+ rubygems_version: 3.3.20
56
56
  signing_key:
57
57
  specification_version: 4
58
58
  summary: Memory profiling routines for Ruby 2.5+