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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/lib/memory_profiler/helpers.rb +1 -1
- data/lib/memory_profiler/reporter.rb +7 -7
- data/lib/memory_profiler/results.rb +32 -22
- data/lib/memory_profiler/top_n.rb +24 -16
- data/lib/memory_profiler/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4c8c5a12cd11ab3f9c5ab852e6bca0cb442ccc25f54997f49243a19aa6cef9b
|
4
|
+
data.tar.gz: 5c0ca217ca3cbc0edca725071512688443ac24a5d3e9f28980d93d3dd30a323f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11d3bf57b920c915a0a98f6cea8798349983b0c64047f481ab1227301ff100a8de16f858ee7d21028d32e3dd04015446f77555bfd050755637714da5d1cc08b3
|
7
|
+
data.tar.gz: 46d2df335163a6ddc35ea3a0eff97573dc7b8a50d671e9aa8940a5acb300ea342d7eb38e10f03f39f3705c4e9ed318a336c68f72ddf39a5cdf4f6bb81b9cc7e5
|
data/CHANGELOG.md
CHANGED
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
|
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
|
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
|
53
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
145
|
-
|
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
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
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
|
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.
|
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:
|
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.
|
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+
|