memory-leak 0.1.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 +7 -0
- checksums.yaml.gz.sig +4 -0
- data/lib/memory/leak/detector.rb +98 -0
- data/lib/memory/leak/version.rb +10 -0
- data/lib/memory/leak.rb +14 -0
- data/license.md +21 -0
- data/readme.md +35 -0
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +74 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b50558351a2324cdddac0369f5b4f81d8787a1b9cee2d92206c997777637ae4
|
4
|
+
data.tar.gz: 7091170b19d36840768f145dbba9bd8f805724af1a2332b60f8ac3df40bb5ed3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4edd0b28026f560e48717721f7f6afcb10798710654758637320ed8dabcd6af8306d68f69d825ab901c78eca027e1172e54e1c970204f2cc7a5e5ac8a0686d0b
|
7
|
+
data.tar.gz: 959f65bc8f7e403cd482d0519d1768e5226b0ed95995dc52a0dca3c9fbc03893e9df7a54b4ad32b49273e1d3919911d93c8965d5e5927157b67c06b80c8da99d
|
checksums.yaml.gz.sig
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
eiM�zK�a�d��]<,�k��.-WZ8V����v*����]/|�P��dž��F��T�y�� ���J�B˰
|
2
|
+
Q+�:��9�a�����#~x����W�����'�Ӧp��H4��V�#=��d,���$���ۨ�<hjN��<�aó����Gk�O��5�[4���{��
|
3
|
+
��p�(l�%5��X����l���z�>��iKv�L�uF{{b�L�+[���
|
4
|
+
�háD������Ǽ�,��4�D�1~��H�u8�=��V��������z������l �'���}��;�]�\��d�'(,� �]�%�\/5+��ڜ��� ����}塥H_��6����Ra0J������1e!�1*��&�PK���`��g^9��
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
require "console"
|
7
|
+
|
8
|
+
module Memory
|
9
|
+
module Leak
|
10
|
+
# Detects memory leaks by tracking heap size increases.
|
11
|
+
#
|
12
|
+
# A memory leak is characterised by the memory usage of the application continuing to rise over time. We can detect this by sampling memory usage and comparing it to the previous sample. If the memory usage is higher than the previous sample, we can say that the application has allocated more memory. Eventually we expect to see this stabilize, but if it continues to rise, we can say that the application has a memory leak.
|
13
|
+
#
|
14
|
+
# We should be careful not to filter historical data, as some memory leaks may only become apparent after a long period of time. Any kind of filtering may prevent us from detecting such a leak.
|
15
|
+
class Detector
|
16
|
+
# We only track heap size changes greater than this threshold (KB), across the DEFAULT_INTERVAL.
|
17
|
+
# True memory leaks will eventually hit this threshold, while small fluctuations will not.
|
18
|
+
DEFAULT_THRESHOLD = 1024*10
|
19
|
+
|
20
|
+
# We track the last N heap size increases.
|
21
|
+
# If the heap size is not stabilizing within the specified limit, we can assume there is a leak.
|
22
|
+
# With a default interval of 10 seconds, this will track the last ~3 minutes of heap size increases.
|
23
|
+
DEFAULT_LIMIT = 20
|
24
|
+
|
25
|
+
# Create a new detector.
|
26
|
+
#
|
27
|
+
# @parameter maximum [Numeric] The initial maximum heap size, from which we willl track increases, in KiB.
|
28
|
+
# @parameter threshold [Numeric] The threshold for heap size increases, in KiB.
|
29
|
+
# @parameter limit [Numeric] The limit for the number of heap size increases, before we assume a memory leak.
|
30
|
+
# @pid [Integer] The process ID to monitor.
|
31
|
+
def initialize(maximum: nil, threshold: DEFAULT_THRESHOLD, limit: DEFAULT_LIMIT, pid: Process.pid)
|
32
|
+
@maximum = maximum
|
33
|
+
@threshold = threshold
|
34
|
+
@limit = limit
|
35
|
+
@pid = pid
|
36
|
+
|
37
|
+
# The number of increasing heap size samples.
|
38
|
+
@count = 0
|
39
|
+
end
|
40
|
+
|
41
|
+
# @attribute [Numeric] The current maximum heap size.
|
42
|
+
attr :maximum
|
43
|
+
|
44
|
+
# @attribute [Numeric] The threshold for heap size increases.
|
45
|
+
attr :threshold
|
46
|
+
|
47
|
+
# @attribute [Numeric] The limit for the number of heap size increases, before we assume a memory leak.
|
48
|
+
attr :limit
|
49
|
+
|
50
|
+
# @attribute [Integer] The number of increasing heap size samples.
|
51
|
+
attr :count
|
52
|
+
|
53
|
+
# The current resident set size (RSS) of the process.
|
54
|
+
#
|
55
|
+
# Even thought the absolute value of this number may not very useful, the relative change is useful for detecting memory leaks, and it works on most platforms.
|
56
|
+
#
|
57
|
+
# @returns [Numeric] Memory usage size in KiB.
|
58
|
+
def memory_usage(pid = @pid)
|
59
|
+
IO.popen(["ps", "-o", "rss=", pid.to_s]) do |io|
|
60
|
+
return Integer(io.readlines.last)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Indicates whether a memory leak has been detected.
|
65
|
+
#
|
66
|
+
# If the number of increasing heap size samples is greater than or equal to the limit, a memory leak is assumed.
|
67
|
+
#
|
68
|
+
# @returns [Boolean] True if a memory leak has been detected.
|
69
|
+
def memory_leak_detected?
|
70
|
+
@count >= @limit
|
71
|
+
end
|
72
|
+
|
73
|
+
# Capture a memory usage sample and yield if a memory leak is detected.
|
74
|
+
#
|
75
|
+
# @yields {|sample, detector| ...} If a memory leak is detected.
|
76
|
+
def capture_sample
|
77
|
+
sample = memory_usage
|
78
|
+
|
79
|
+
if @maximum
|
80
|
+
delta = sample - @maximum
|
81
|
+
Console.debug(self, "Heap size captured.", sample: sample, delta: delta, threshold: @threshold, maximum: @maximum)
|
82
|
+
|
83
|
+
if delta > @threshold
|
84
|
+
@maximum = sample
|
85
|
+
@count += 1
|
86
|
+
|
87
|
+
Console.debug(self, "Heap size increased.", maximum: @maximum, count: @count)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
Console.debug(self, "Initial heap size captured.", sample: sample)
|
91
|
+
@maximum = sample
|
92
|
+
end
|
93
|
+
|
94
|
+
return sample
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/memory/leak.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative "leak/version"
|
7
|
+
require_relative "leak/detector"
|
8
|
+
|
9
|
+
# @namespace
|
10
|
+
module Memory
|
11
|
+
# @namespace
|
12
|
+
module Leak
|
13
|
+
end
|
14
|
+
end
|
data/license.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# MIT License
|
2
|
+
|
3
|
+
Copyright, 2025, by Samuel Williams.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/readme.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Memory::Leak
|
2
|
+
|
3
|
+
Detects memory leaks in Ruby applications.
|
4
|
+
|
5
|
+
[](https://github.com/socketry/memory-leak/actions?workflow=Test)
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Please see the [project documentation](https://socketry.github.io/memory-leak/) for more details.
|
10
|
+
|
11
|
+
## Releases
|
12
|
+
|
13
|
+
Please see the [project releases](https://socketry.github.io/memory-leak/releases/index) for all releases.
|
14
|
+
|
15
|
+
### v0.1.0
|
16
|
+
|
17
|
+
- Initial implementation.
|
18
|
+
|
19
|
+
## Contributing
|
20
|
+
|
21
|
+
We welcome contributions to this project.
|
22
|
+
|
23
|
+
1. Fork it.
|
24
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
25
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
26
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
27
|
+
5. Create new Pull Request.
|
28
|
+
|
29
|
+
### Developer Certificate of Origin
|
30
|
+
|
31
|
+
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
32
|
+
|
33
|
+
### Community Guidelines
|
34
|
+
|
35
|
+
This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
|
data/releases.md
ADDED
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: memory-leak
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Williams
|
8
|
+
bindir: bin
|
9
|
+
cert_chain:
|
10
|
+
- |
|
11
|
+
-----BEGIN CERTIFICATE-----
|
12
|
+
MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
|
13
|
+
ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
|
14
|
+
CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
|
15
|
+
MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
|
16
|
+
MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
|
17
|
+
bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
|
18
|
+
igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
|
19
|
+
9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
|
20
|
+
sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
|
21
|
+
e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
|
22
|
+
XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
|
23
|
+
RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
|
24
|
+
tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
|
25
|
+
zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
|
26
|
+
xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
27
|
+
BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
|
28
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
|
29
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
|
30
|
+
cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
|
31
|
+
xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
|
32
|
+
c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
|
33
|
+
8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
|
34
|
+
JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
|
35
|
+
eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
|
36
|
+
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
37
|
+
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
38
|
+
-----END CERTIFICATE-----
|
39
|
+
date: 2025-02-24 00:00:00.000000000 Z
|
40
|
+
dependencies: []
|
41
|
+
executables: []
|
42
|
+
extensions: []
|
43
|
+
extra_rdoc_files: []
|
44
|
+
files:
|
45
|
+
- lib/memory/leak.rb
|
46
|
+
- lib/memory/leak/detector.rb
|
47
|
+
- lib/memory/leak/version.rb
|
48
|
+
- license.md
|
49
|
+
- readme.md
|
50
|
+
- releases.md
|
51
|
+
homepage: https://github.com/socketry/memory-leak
|
52
|
+
licenses:
|
53
|
+
- MIT
|
54
|
+
metadata:
|
55
|
+
documentation_uri: https://socketry.github.io/memory-leak/
|
56
|
+
source_code_uri: https://github.com/socketry/memory-leak.git
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '3.1'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.6.2
|
72
|
+
specification_version: 4
|
73
|
+
summary: A memory leak detector.
|
74
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|