memory 0.6.0 → 0.6.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
- checksums.yaml.gz.sig +2 -4
- data/context/getting-started.md +238 -0
- data/context/index.yaml +12 -0
- data/lib/memory/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8ab40ebc992286597b6a01b5157fca5393b29563c7131483d2e7839f15172541
|
|
4
|
+
data.tar.gz: d5b9b73ea305840435c242a6e34bf755d94e77350846f6618467fef4fa7561ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a10c287ab778c7deb2e12b5a04e7214107ae7afbdf12e57af3423128fe0dc9c233735892ae97ec18d90f47ba46856f08ab5624389a1cb61dbdc4d9af3733bf3
|
|
7
|
+
data.tar.gz: db0d83a8c69a4bdf37e058d6a9e304a7b0608791f8a1f89ad1f2864f2d4119aa8c61c9726b813800e4b45506e1cfa2eec7227ca8eeed99170b931927878e4efb
|
checksums.yaml.gz.sig
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
��V�K��q%o¯ڄ�?i4b�@�Y_�@���:�k�9��`ȁ2dR�x����5�������I'(����W�Ѕ#(T��G40q�UtT³{�H���C�t�J(��hjf_�%*Q�2�4�T%�.�:#fK���Gi�P�Z���h���nh�ڥ�ȇwS�vƏ�;&�
|
|
4
|
-
�ČTk[wr��t�k�vN���&��c}Rn�cA�J�c�`�S��`������/x�� ��H�Ř�>
|
|
1
|
+
5�^�R�M�(�KD��n����^�z<~�"�i�yAP����Qt��p�<D��2jlyIe�xf ���W�bS��:L�n��@
|
|
2
|
+
g��A]�%��Pn�fG>b��?x�#�ն�h� ���D�&y
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide explains how to get started with `memory`, a Ruby gem for profiling memory allocations in your applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add the gem to your project:
|
|
8
|
+
|
|
9
|
+
``` bash
|
|
10
|
+
$ bundle add memory
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Core Concepts
|
|
14
|
+
|
|
15
|
+
`memory` helps you understand where your Ruby application allocates memory and which allocations are retained (not garbage collected). It has several core concepts:
|
|
16
|
+
|
|
17
|
+
- A {ruby Memory::Sampler} which captures allocation data during code execution.
|
|
18
|
+
- A {ruby Memory::Report} which aggregates and presents allocation statistics.
|
|
19
|
+
- A {ruby Memory::Aggregate} which groups allocations by specific metrics (gem, file, class, etc.).
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
The simplest way to profile memory allocations is using the `Memory.report` method:
|
|
24
|
+
|
|
25
|
+
``` ruby
|
|
26
|
+
require "memory"
|
|
27
|
+
|
|
28
|
+
# Profile a block of code:
|
|
29
|
+
report = Memory.report do
|
|
30
|
+
# Your code here - e.g., process 1000 user records:
|
|
31
|
+
users = []
|
|
32
|
+
1000.times do |i|
|
|
33
|
+
users << {id: i, name: "User #{i}", email: "user#{i}@example.com"}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Process the data:
|
|
37
|
+
users.each do |user|
|
|
38
|
+
formatted = "#{user[:name]} <#{user[:email]}>"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Display the results:
|
|
43
|
+
report.print
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This will output a detailed report showing:
|
|
47
|
+
|
|
48
|
+
- **Total Allocated**: All objects created during execution
|
|
49
|
+
- **Total Retained**: Objects that survived garbage collection
|
|
50
|
+
- **By Gem**: Memory usage grouped by gem/library
|
|
51
|
+
- **By File**: Memory usage grouped by source file
|
|
52
|
+
- **By Location**: Memory usage by specific file:line locations
|
|
53
|
+
- **By Class**: Memory usage by object class
|
|
54
|
+
- **Strings**: Special analysis of string allocations
|
|
55
|
+
|
|
56
|
+
### Understanding the Output
|
|
57
|
+
|
|
58
|
+
The report shows memory allocations in human-readable units (B, KiB, MiB, etc.):
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
# Retained Memory Profile
|
|
62
|
+
|
|
63
|
+
- Total Allocated: (1.50 MiB in 15234 allocations)
|
|
64
|
+
- Total Retained: (856.32 KiB in 8912 allocations)
|
|
65
|
+
|
|
66
|
+
## By Gem (856.32 KiB in 8912 allocations)
|
|
67
|
+
|
|
68
|
+
- (645.21 KiB in 6543 allocations) my_app/lib
|
|
69
|
+
- (128.45 KiB in 1234 allocations) activerecord-7.0.8
|
|
70
|
+
- (82.66 KiB in 1135 allocations) activesupport-7.0.8
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Each line shows:
|
|
74
|
+
- The memory consumed and number of allocations in that category
|
|
75
|
+
- The category name (gem, file, class, etc.)
|
|
76
|
+
|
|
77
|
+
### Manual Start/Stop
|
|
78
|
+
|
|
79
|
+
For more control, use the {ruby Memory::Sampler} directly:
|
|
80
|
+
|
|
81
|
+
``` ruby
|
|
82
|
+
require "memory"
|
|
83
|
+
|
|
84
|
+
sampler = Memory::Sampler.new
|
|
85
|
+
|
|
86
|
+
# Start profiling:
|
|
87
|
+
sampler.start
|
|
88
|
+
|
|
89
|
+
# Run your code:
|
|
90
|
+
items = []
|
|
91
|
+
10000.times do |i|
|
|
92
|
+
items << "Item #{i}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Stop profiling:
|
|
96
|
+
sampler.stop
|
|
97
|
+
|
|
98
|
+
# Generate and print the report:
|
|
99
|
+
report = sampler.report
|
|
100
|
+
report.print
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This approach is useful when:
|
|
104
|
+
- You need to profile specific sections of long-running code
|
|
105
|
+
- You want to control exactly when profiling begins and ends
|
|
106
|
+
- You're integrating with test frameworks or benchmarking tools
|
|
107
|
+
|
|
108
|
+
### Filtering Allocations
|
|
109
|
+
|
|
110
|
+
You can filter which allocations to track by providing a filter block to {ruby Memory::Sampler}:
|
|
111
|
+
|
|
112
|
+
``` ruby
|
|
113
|
+
# Only track String allocations from your application code:
|
|
114
|
+
sampler = Memory::Sampler.new do |klass, file|
|
|
115
|
+
klass == String && file.include?("/lib/my_app/")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
sampler.start
|
|
119
|
+
# Your code here
|
|
120
|
+
sampler.stop
|
|
121
|
+
|
|
122
|
+
report = sampler.report
|
|
123
|
+
report.print
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The filter block receives:
|
|
127
|
+
- `klass`: The class of the allocated object
|
|
128
|
+
- `file`: The source file where the allocation occurred
|
|
129
|
+
|
|
130
|
+
Return `true` to include the allocation, `false` to exclude it.
|
|
131
|
+
|
|
132
|
+
### Persisting Results
|
|
133
|
+
|
|
134
|
+
For analyzing large applications or comparing runs over time, you can persist allocation data to disk:
|
|
135
|
+
|
|
136
|
+
``` ruby
|
|
137
|
+
sampler = Memory::Sampler.new
|
|
138
|
+
|
|
139
|
+
sampler.start
|
|
140
|
+
# Run your code
|
|
141
|
+
sampler.stop
|
|
142
|
+
|
|
143
|
+
# Save the allocation data:
|
|
144
|
+
File.open("profile.mprof", "w", encoding: Encoding::BINARY) do |io|
|
|
145
|
+
sampler.dump(io)
|
|
146
|
+
end
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Later, you can load and analyze the data:
|
|
150
|
+
|
|
151
|
+
``` ruby
|
|
152
|
+
sampler = Memory::Sampler.new
|
|
153
|
+
|
|
154
|
+
# Load saved allocation data:
|
|
155
|
+
data = File.read("profile.mprof", encoding: Encoding::BINARY)
|
|
156
|
+
sampler.load(data)
|
|
157
|
+
|
|
158
|
+
# Generate a report:
|
|
159
|
+
report = sampler.report
|
|
160
|
+
report.print
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
You can even combine multiple profile files:
|
|
164
|
+
|
|
165
|
+
``` ruby
|
|
166
|
+
sampler = Memory::Sampler.new
|
|
167
|
+
|
|
168
|
+
# Load multiple profile files:
|
|
169
|
+
Dir.glob("profiles/*.mprof") do |path|
|
|
170
|
+
puts "Loading #{path}..."
|
|
171
|
+
sampler.load(File.read(path, encoding: Encoding::BINARY))
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Generate a combined report:
|
|
175
|
+
report = sampler.report
|
|
176
|
+
report.print
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
This is particularly useful for:
|
|
180
|
+
- **Profiling test suites**: Profile each test file separately, then combine results
|
|
181
|
+
- **Production analysis**: Capture profiles from production environments and analyze offline
|
|
182
|
+
- **Trend analysis**: Compare memory usage across different code versions
|
|
183
|
+
|
|
184
|
+
### Custom Reports
|
|
185
|
+
|
|
186
|
+
You can create custom reports with specific aggregates:
|
|
187
|
+
|
|
188
|
+
``` ruby
|
|
189
|
+
require "memory"
|
|
190
|
+
|
|
191
|
+
# Create a custom report with only specific aggregates:
|
|
192
|
+
report = Memory::Report.new([
|
|
193
|
+
Memory::Aggregate.new("By Class", &:class_name),
|
|
194
|
+
Memory::Aggregate.new("By Gem", &:gem)
|
|
195
|
+
], retained_only: true)
|
|
196
|
+
|
|
197
|
+
sampler = Memory::Sampler.new
|
|
198
|
+
sampler.run do
|
|
199
|
+
# Your code here
|
|
200
|
+
10000.times {"test string"}
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Add samples to the custom report:
|
|
204
|
+
report.add(sampler)
|
|
205
|
+
report.print
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The `retained_only: true` option (default) focuses on memory leaks by only showing allocations that weren't garbage collected. Set it to `false` to see all allocations:
|
|
209
|
+
|
|
210
|
+
``` ruby
|
|
211
|
+
# Show all allocations, not just retained ones:
|
|
212
|
+
report = Memory::Report.new([
|
|
213
|
+
Memory::Aggregate.new("By Class", &:class_name)
|
|
214
|
+
], retained_only: false)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Exporting to JSON
|
|
218
|
+
|
|
219
|
+
Reports can be exported as JSON for integration with other tools:
|
|
220
|
+
|
|
221
|
+
``` ruby
|
|
222
|
+
report = Memory.report do
|
|
223
|
+
# Your code
|
|
224
|
+
data = Array.new(1000) {{value: rand(1000)}}
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Export as JSON:
|
|
228
|
+
json_output = report.to_json
|
|
229
|
+
puts json_output
|
|
230
|
+
|
|
231
|
+
# Or as a Ruby hash:
|
|
232
|
+
hash_output = report.as_json
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
This is useful for:
|
|
236
|
+
- Building custom visualization tools.
|
|
237
|
+
- Integrating with CI/CD pipelines.
|
|
238
|
+
- Tracking memory metrics over time in dashboards.
|
data/context/index.yaml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Automatically generated context index for Utopia::Project guides.
|
|
2
|
+
# Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
|
|
3
|
+
---
|
|
4
|
+
description: Memory profiling routines for Ruby 2.3+
|
|
5
|
+
metadata:
|
|
6
|
+
documentation_uri: https://socketry.github.io/memory/
|
|
7
|
+
source_code_uri: https://github.com/socketry/memory.git
|
|
8
|
+
files:
|
|
9
|
+
- path: getting-started.md
|
|
10
|
+
title: Getting Started
|
|
11
|
+
description: This guide explains how to get started with `memory`, a Ruby gem for
|
|
12
|
+
profiling memory allocations in your applications.
|
data/lib/memory/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sam Saffron
|
|
@@ -110,6 +110,8 @@ extra_rdoc_files: []
|
|
|
110
110
|
files:
|
|
111
111
|
- bake/memory/report.rb
|
|
112
112
|
- bake/memory/sampler.rb
|
|
113
|
+
- context/getting-started.md
|
|
114
|
+
- context/index.yaml
|
|
113
115
|
- lib/memory.rb
|
|
114
116
|
- lib/memory/aggregate.rb
|
|
115
117
|
- lib/memory/cache.rb
|
metadata.gz.sig
CHANGED
|
Binary file
|