memory 0.6.1 → 0.7.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: 8ab40ebc992286597b6a01b5157fca5393b29563c7131483d2e7839f15172541
4
- data.tar.gz: d5b9b73ea305840435c242a6e34bf755d94e77350846f6618467fef4fa7561ff
3
+ metadata.gz: 266bdfec74c35392a9c086c366df9bb6ab4fb5e1b162b98d3757f690fff09ded
4
+ data.tar.gz: dffe8472314144b5786b5c445c6e01973114e9c3915d08aae0352fc1be76d329
5
5
  SHA512:
6
- metadata.gz: 5a10c287ab778c7deb2e12b5a04e7214107ae7afbdf12e57af3423128fe0dc9c233735892ae97ec18d90f47ba46856f08ab5624389a1cb61dbdc4d9af3733bf3
7
- data.tar.gz: db0d83a8c69a4bdf37e058d6a9e304a7b0608791f8a1f89ad1f2864f2d4119aa8c61c9726b813800e4b45506e1cfa2eec7227ca8eeed99170b931927878e4efb
6
+ metadata.gz: 4dcf3e65b4a7dee68b55919dc44004149a6febe80fde00d539d2b0361eea62dd47ab742006ef7ed75a2980829f0f58cbf1c341098ae394ac4ac3b7a4d816752b
7
+ data.tar.gz: '038621f8d88603eb8b0b2a89fe13e4007bc100ce0c16c53febd9d02a6cf4fa3a00c6c3e967bfa8a6aa6507e3611266cae774dc016d330fe5b22d5322beee12e3'
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- 5�^�R�M�(�KD��n����^�z<~�"iyAP����Qt��p�<D��2jlyIe�xf ���W�bS��:L�n��@
2
- g��A]�%��Pn�fG>b��?x�#�ն�h� ���D�&y
1
+ =��z�6r��g9��j�V�,��$�$0�����SP��.��?֋�Yb
2
+ �F�$��}����rM�|H�n���U�̮�T��q��`�i0� q��zA=b:���@)��������3�;p������-N�����6.$Zc��] �d���O�{@"���M���?���SWQ�-�
@@ -5,7 +5,7 @@
5
5
 
6
6
  def initialize(...)
7
7
  super
8
-
8
+
9
9
  require_relative "../../lib/memory"
10
10
  end
11
11
 
@@ -26,6 +26,6 @@ def print(input:)
26
26
  end
27
27
 
28
28
  report.print($stderr)
29
-
29
+
30
30
  return report
31
31
  end
@@ -6,7 +6,7 @@
6
6
  def initialize(...)
7
7
  super
8
8
 
9
- require_relative '../../lib/memory'
9
+ require_relative "../../lib/memory"
10
10
  end
11
11
 
12
12
  # Load a sampler from one or more .mprof files.
@@ -27,7 +27,7 @@ def load(paths:)
27
27
  paths.each do |path|
28
28
  Console.logger.info(sampler, "Loading #{path}, #{Memory.formatted_bytes File.size(path)}")
29
29
 
30
- File.open(path, 'r', encoding: Encoding::BINARY) do |io|
30
+ File.open(path, "r", encoding: Encoding::BINARY) do |io|
31
31
  unpacker = wrapper.unpacker(io)
32
32
  count = unpacker.read_array_header
33
33
 
@@ -56,7 +56,7 @@ end
56
56
  # @parameter output [String] Path to write the .mprof file.
57
57
  # @returns [Memory::Sampler] The input sampler.
58
58
  def dump(path, input:)
59
- File.open(path, 'w', encoding: Encoding::BINARY) do |io|
59
+ File.open(path, "w", encoding: Encoding::BINARY) do |io|
60
60
  input.dump(io)
61
61
  end
62
62
 
@@ -76,7 +76,7 @@ def load_object_space_dump(path)
76
76
  Console.logger.info(self, "Loading heap dump from #{path} (#{Memory.formatted_bytes(file_size)})")
77
77
 
78
78
  sampler = nil
79
- File.open(path, 'r') do |io|
79
+ File.open(path, "r") do |io|
80
80
  sampler = Memory::Sampler.load_object_space_dump(io) do |line_count, object_count|
81
81
  # Update progress based on bytes read:
82
82
  progress.increment(io.pos - progress.current)
data/lib/memory/report.rb CHANGED
@@ -90,16 +90,16 @@ module Memory
90
90
  }
91
91
  end
92
92
 
93
- # Convert this report to a JSON string.
94
- # @returns [String] JSON representation of this report.
95
- def to_json(...)
96
- as_json.to_json(...)
97
- end
98
-
99
- # Generate a human-readable representation of this report.
100
- # @returns [String] Summary showing allocated and retained totals.
101
- def inspect
102
- "#<#{self.class}: #{@total_allocated} allocated, #{@total_retained} retained>"
93
+ # Convert this report to a JSON string.
94
+ # @returns [String] JSON representation of this report.
95
+ def to_json(...)
96
+ as_json.to_json(...)
97
+ end
98
+
99
+ # Generate a human-readable representation of this report.
100
+ # @returns [String] Summary showing allocated and retained totals.
101
+ def inspect
102
+ "#<#{self.class}: #{@total_allocated} allocated, #{@total_retained} retained>"
103
+ end
103
104
  end
104
105
  end
105
- end
@@ -66,72 +66,72 @@ module Memory
66
66
  # end
67
67
  # ~~~
68
68
  class Sampler
69
- # Load allocations from an ObjectSpace heap dump.
70
- #
71
- # If a block is given, it will be called periodically with progress information.
72
- #
73
- # @parameter io [IO] The IO stream containing the heap dump JSON.
74
- # @yields [line_count, object_count] Progress callback with current line and object counts.
75
- # @returns [Sampler] A new sampler populated with allocations from the heap dump.
76
- def self.load_object_space_dump(io, &block)
77
- sampler = new
78
- cache = sampler.cache
79
-
80
- line_count = 0
81
- object_count = 0
82
- report_interval = 10000
83
-
84
- io.each_line do |line|
85
- line_count += 1
86
-
87
- begin
88
- object = JSON.parse(line)
89
- rescue JSON::ParserError
90
- # Skip invalid JSON lines
91
- next
92
- end
93
-
94
- # Skip non-object entries (ROOT, SHAPE, etc.)
95
- next unless object['address']
69
+ # Load allocations from an ObjectSpace heap dump.
70
+ #
71
+ # If a block is given, it will be called periodically with progress information.
72
+ #
73
+ # @parameter io [IO] The IO stream containing the heap dump JSON.
74
+ # @yields [line_count, object_count] Progress callback with current line and object counts.
75
+ # @returns [Sampler] A new sampler populated with allocations from the heap dump.
76
+ def self.load_object_space_dump(io, &block)
77
+ sampler = new
78
+ cache = sampler.cache
96
79
 
97
- # Get allocation information (may be nil if tracing wasn't enabled)
98
- file = object['file'] || '(unknown)'
99
- line_number = object['line'] || 0
80
+ line_count = 0
81
+ object_count = 0
82
+ report_interval = 10000
100
83
 
101
- # Get object type/class
102
- type = object['type'] || 'unknown'
103
-
104
- # Get memory size
105
- memsize = object['memsize'] || 0
106
-
107
- # Get value for strings
108
- value = object['value']
109
-
110
- allocation = Allocation.new(
111
- cache,
112
- type, # class_name
113
- file, # file
114
- line_number, # line
115
- memsize, # memsize
116
- value, # value (for strings)
117
- true # retained (all objects in heap dump are live)
118
- )
84
+ io.each_line do |line|
85
+ line_count += 1
86
+
87
+ begin
88
+ object = JSON.parse(line)
89
+ rescue JSON::ParserError
90
+ # Skip invalid JSON lines
91
+ next
92
+ end
93
+
94
+ # Skip non-object entries (ROOT, SHAPE, etc.)
95
+ next unless object["address"]
96
+
97
+ # Get allocation information (may be nil if tracing wasn't enabled)
98
+ file = object["file"] || "(unknown)"
99
+ line_number = object["line"] || 0
100
+
101
+ # Get object type/class
102
+ type = object["type"] || "unknown"
103
+
104
+ # Get memory size
105
+ memsize = object["memsize"] || 0
106
+
107
+ # Get value for strings
108
+ value = object["value"]
109
+
110
+ allocation = Allocation.new(
111
+ cache,
112
+ type, # class_name
113
+ file, # file
114
+ line_number, # line
115
+ memsize, # memsize
116
+ value, # value (for strings)
117
+ true # retained (all objects in heap dump are live)
118
+ )
119
+
120
+ sampler.allocated << allocation
121
+ object_count += 1
122
+
123
+ # Report progress periodically
124
+ if block && (object_count % report_interval == 0)
125
+ block.call(line_count, object_count)
126
+ end
127
+ end
119
128
 
120
- sampler.allocated << allocation
121
- object_count += 1
129
+ # Final progress report
130
+ block.call(line_count, object_count) if block
122
131
 
123
- # Report progress periodically
124
- if block && (object_count % report_interval == 0)
125
- block.call(line_count, object_count)
126
- end
132
+ return sampler
127
133
  end
128
134
 
129
- # Final progress report
130
- block.call(line_count, object_count) if block
131
-
132
- return sampler
133
- end
134
-
135
135
  # Initialize a new sampler.
136
136
  # @parameter filter [Block | Nil] Optional filter block to select which allocations to track.
137
137
  def initialize(&filter)
@@ -231,6 +231,22 @@ module Memory
231
231
  return report
232
232
  end
233
233
 
234
+ # Convert this sampler to a JSON-compatible summary.
235
+ # Returns the allocation count without iterating through all allocations.
236
+ # @parameter options [Hash | Nil] Optional JSON serialization options.
237
+ # @returns [Hash] JSON-compatible summary of sampler data.
238
+ def as_json(options = nil)
239
+ {
240
+ allocations: @allocated.size
241
+ }
242
+ end
243
+
244
+ # Convert this sampler to a JSON string.
245
+ # @returns [String] JSON representation of this sampler summary.
246
+ def to_json(...)
247
+ as_json.to_json(...)
248
+ end
249
+
234
250
  # Collects object allocation and memory of ruby code inside of passed block.
235
251
  def run(&block)
236
252
  start
@@ -4,8 +4,8 @@
4
4
  # Copyright, 2013-2019, by Sam Saffron.
5
5
  # Copyright, 2015-2016, by Dave Gynn.
6
6
  # Copyright, 2018, by Jonas Peschla.
7
- # Copyright, 2020-2024, by Samuel Williams.
7
+ # Copyright, 2020-2025, by Samuel Williams.
8
8
 
9
9
  module Memory
10
- VERSION = "0.6.1"
10
+ VERSION = "0.7.0"
11
11
  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.7.0
98
+
99
+ - Add `Memory::Sampler#as_json` and `#to_json`.
100
+
97
101
  ### v0.6.0
98
102
 
99
103
  - Add agent context.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.7.0
4
+
5
+ - Add `Memory::Sampler#as_json` and `#to_json`.
6
+
3
7
  ## v0.6.0
4
8
 
5
9
  - Add agent context.
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.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
metadata.gz.sig CHANGED
Binary file