memory_profiler 1.0.0 → 1.0.1

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