memory 0.11.0 → 0.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91e6bf9d1a607a68dd5d8f368d6dfe4a4319bf5730b6283194f99fb587b96364
4
- data.tar.gz: 9a4335bfa899416c7fec144236dc5e711382f49f5631a4b0dbde03d73e84a58e
3
+ metadata.gz: 629175076a1c5aaf4cc1c75ea5bd8bcbb2b0366a2bfab17b6b95dc6b5834db12
4
+ data.tar.gz: 5a9a623b425a324c3d9692e1d20bda001cbc6de12c9e6c01035044964ecb5942
5
5
  SHA512:
6
- metadata.gz: 0a704a533f5ac299f5b0da35814c7d93d13dc9881fda6c69c8f274a9331dedf3f9b57e1afa22b28888892092f2daf9a0c583259fbcbf26757d2f3c3805594caf
7
- data.tar.gz: cc67f1e0781d93b648ed720efb1a4ce6d05c5d18c15e2b781ecbb00321fec08c674d2be2a051f1835bf9de1f2e1a90c5ee6df4be72ac46d0e4ba6f50ec48f5f5
6
+ metadata.gz: 28d5d336d183df4140d6ab94a24ed69974598daa544ece8590cd37d3e0be7d3dbe38db69a6965eacb35107822cc1af93efd8bcf85d6f49076c73b8490b5ac603
7
+ data.tar.gz: aefccd3ad62ff34cd869ef52709f82b44323e273dd96da80ecf8af8a792cfc69bbea32f6b44011fd08e8bb9364e758bccb6685dcd8fc042e18c372b01b2d7137
checksums.yaml.gz.sig CHANGED
Binary file
@@ -197,7 +197,7 @@ report = Memory::Report.new([
197
197
  sampler = Memory::Sampler.new
198
198
  sampler.run do
199
199
  # Your code here
200
- 10000.times {"test string"}
200
+ 10000.times{"test string"}
201
201
  end
202
202
 
203
203
  # Add samples to the custom report:
@@ -221,7 +221,7 @@ Reports can be exported as JSON for integration with other tools:
221
221
  ``` ruby
222
222
  report = Memory.report do
223
223
  # Your code
224
- data = Array.new(1000) {{value: rand(1000)}}
224
+ data = Array.new(1000){{value: rand(1000)}}
225
225
  end
226
226
 
227
227
  # Export as JSON:
data/lib/memory/cache.rb CHANGED
@@ -17,7 +17,7 @@ module Memory
17
17
  # Initialize a new cache with empty lookup tables.
18
18
  def initialize
19
19
  @gem_guess_cache = Hash.new
20
- @location_cache = Hash.new {|h, k| h[k] = Hash.new.compare_by_identity}
20
+ @location_cache = Hash.new{|h, k| h[k] = Hash.new.compare_by_identity}
21
21
  @class_name_cache = Hash.new.compare_by_identity
22
22
  @string_cache = Hash.new
23
23
  end
@@ -56,14 +56,22 @@ module Memory
56
56
  end
57
57
 
58
58
  # Look up and cache a string value.
59
+ #
60
+ # This maps the original string to a shortened representation.
61
+ #
59
62
  # Strings are truncated to 64 characters to reduce memory usage.
60
63
  # @parameter obj [String] The string object to cache.
61
64
  # @returns [String] A cached copy of the string (truncated to 64 characters).
62
65
  def lookup_string(obj)
63
- # This string is shortened to 200 characters which is what the string report shows
64
- # The string report can still list unique strings longer than 200 characters
65
- # separately because the object_id of the shortened string will be different
66
- @string_cache[obj] ||= String.new << obj[0, 64]
66
+ # This string is shortened to 64 characters which is what the string report shows. The string report (by value) can still list unique strings longer than 64 characters separately because the `object_id` of the shortened string will be different.
67
+ @string_cache[obj] ||= obj[0, 64]
68
+ rescue RuntimeError => error
69
+ # It is possible for the String to be temporarily locked from another Fiber which raises an error when we try to use it as a hash key. i.e: `Socket#read` locks a buffer string while reading data into it. In this case we `#dup`` the string to get an unlocked copy.
70
+ if error.message == "can't modify string; temporarily locked"
71
+ @string_cache[obj.dup] ||= obj[0, 64]
72
+ else
73
+ raise
74
+ end
67
75
  end
68
76
  end
69
77
  end
data/lib/memory/graph.rb CHANGED
@@ -13,6 +13,11 @@ module Memory
13
13
 
14
14
  # Represents a node in the object graph with usage information.
15
15
  class Node
16
+ # Initialize a new node in the object graph.
17
+ # @parameter object [Object] The object this node represents.
18
+ # @parameter usage [Usage] The memory usage of this object.
19
+ # @parameter parent [Node | Nil] The parent node in the traversal tree.
20
+ # @parameter reference [Symbol | Nil] The reference type from parent to this object.
16
21
  def initialize(object, usage = Usage.new, parent = nil, reference: nil)
17
22
  @object = object
18
23
  @usage = usage
@@ -151,16 +156,21 @@ module Memory
151
156
  # @parameter options [Hash] Options for JSON serialization.
152
157
  # @returns [Hash] A hash representation of this node.
153
158
  def as_json(*)
154
- {
159
+ json = {
155
160
  path: path,
156
- object: {
157
- class: @object.class.name,
158
- object_id: @object.object_id
159
- },
160
- usage: @usage.as_json,
161
- total_usage: total_usage.as_json,
162
- children: @children&.transform_values(&:as_json)
161
+ object: {
162
+ class: @object.class.name,
163
+ object_id: @object.object_id
164
+ },
165
+ usage: @usage.as_json,
163
166
  }
167
+
168
+ if @children&.any?
169
+ json[:total_usage] = total_usage.as_json
170
+ json[:children] = @children.transform_values(&:as_json)
171
+ end
172
+
173
+ return json
164
174
  end
165
175
 
166
176
  # Convert this node to a JSON string.
@@ -32,8 +32,8 @@ module Memory
32
32
  @cache = cache
33
33
 
34
34
  self.register_type(0x01, Allocation,
35
- packer: ->(instance){self.pack(instance.pack)},
36
- unpacker: ->(data){Allocation.unpack(@cache, self.unpack(data))},
35
+ packer: ->(instance) {self.pack(instance.pack)},
36
+ unpacker: ->(data) {Allocation.unpack(@cache, self.unpack(data))},
37
37
  )
38
38
 
39
39
  self.register_type(0x02, Symbol)
@@ -290,9 +290,6 @@ module Memory
290
290
  class_name = @cache.lookup_class_name(klass)
291
291
  value = (klass == String) ? @cache.lookup_string(object) : nil
292
292
 
293
- # compensate for API bug
294
- memsize = rvalue_size if memsize > 100_000_000_000
295
-
296
293
  allocation = Allocation.new(@cache, class_name, file, line, memsize, value, false)
297
294
 
298
295
  @allocated << allocation
data/lib/memory/usage.rb CHANGED
@@ -9,7 +9,13 @@ require "set"
9
9
  require "objspace"
10
10
 
11
11
  module Memory
12
+ # Tracks memory usage statistics including size and object count.
13
+ #
14
+ # Can be used to measure allocations or compute usage of object graphs.
12
15
  class Usage
16
+ # Initialize a new usage tracker.
17
+ # @parameter size [Integer] The total size in bytes.
18
+ # @parameter count [Integer] The total count of objects.
13
19
  def initialize(size = 0, count = 0)
14
20
  @size = size
15
21
  @count = count
@@ -103,17 +109,24 @@ module Memory
103
109
  return new(size, count)
104
110
  end
105
111
 
112
+ # Convert this usage to a JSON-compatible hash.
113
+ # @parameter options [Hash | Nil] Optional JSON serialization options.
114
+ # @returns [Hash] Hash with `:size` and `:count` keys.
106
115
  def as_json(...)
107
116
  {
108
117
  size: @size,
109
- count: @count
118
+ count: @count
110
119
  }
111
120
  end
112
121
 
122
+ # Convert this usage to a JSON string.
123
+ # @returns [String] JSON representation of this usage.
113
124
  def to_json(...)
114
125
  as_json.to_json(...)
115
126
  end
116
127
 
128
+ # Generate a human-readable string representation.
129
+ # @returns [String] Formatted string showing size and allocation count.
117
130
  def to_s
118
131
  "(#{Memory.formatted_bytes(@size)} in #{@count} allocations)"
119
132
  end
@@ -7,5 +7,5 @@
7
7
  # Copyright, 2020-2025, by Samuel Williams.
8
8
 
9
9
  module Memory
10
- VERSION = "0.11.0"
10
+ VERSION = "0.12.0"
11
11
  end
data/lib/memory.rb CHANGED
@@ -37,4 +37,12 @@ module Memory
37
37
  def self.report(&block)
38
38
  self.capture(&block)
39
39
  end
40
+
41
+ # @namespace Used by the `memory-profiler` gem.
42
+ module Profiler
43
+ end
44
+
45
+ # @namespace Used by the `memory-leaks` gem.
46
+ module Leaks
47
+ end
40
48
  end
data/readme.md CHANGED
@@ -94,6 +94,10 @@ end
94
94
 
95
95
  Please see the [project releases](https://socketry.github.io/memory/releases/index) for all releases.
96
96
 
97
+ ### v0.11.1
98
+
99
+ - Compressed `Memory::Graph::Node` JSON representation for leaf nodes.
100
+
97
101
  ### v0.11.0
98
102
 
99
103
  - Remove support for `Memory::Usage.of(..., via:)` and instead use `Memory::Graph.for` which collects more detailed usage until the specified depth, at which point it delgates to `Memory::Usage.of`. This should be more practical.
@@ -132,10 +136,6 @@ Please see the [project releases](https://socketry.github.io/memory/releases/ind
132
136
 
133
137
  - Ensure aggregate keys are safe for serialization (and printing).
134
138
 
135
- ### v0.7.0
136
-
137
- - Add `Memory::Sampler#as_json` and `#to_json`.
138
-
139
139
  ## Contributing
140
140
 
141
141
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.11.1
4
+
5
+ - Compressed `Memory::Graph::Node` JSON representation for leaf nodes.
6
+
3
7
  ## v0.11.0
4
8
 
5
9
  - Remove support for `Memory::Usage.of(..., via:)` and instead use `Memory::Graph.for` which collects more detailed usage until the specified depth, at which point it delgates to `Memory::Usage.of`. This should be more practical.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
@@ -29,6 +29,7 @@ authors:
29
29
  - Olle Jonsson
30
30
  - Vasily Kolesnikov
31
31
  - William Tabi
32
+ - Michael Go
32
33
  bindir: bin
33
34
  cert_chain:
34
35
  - |
@@ -145,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
146
  - !ruby/object:Gem::Version
146
147
  version: '0'
147
148
  requirements: []
148
- rubygems_version: 3.7.2
149
+ rubygems_version: 3.6.9
149
150
  specification_version: 4
150
151
  summary: Memory profiling routines for Ruby 2.3+
151
152
  test_files: []
metadata.gz.sig CHANGED
Binary file