leak_profiler 0.7.6 → 0.8.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: 72f8b0c66ed134b82f8c7c4a5c1c19939962a8bd7cd2227df7e6e1fb695eaceb
4
- data.tar.gz: 5e0a015723cb449c3cf3154f7d47da2e7ef20e001c8ae3d3b8a2339699cb11c9
3
+ metadata.gz: 85fbefd746a7383bc1891bea286e39be5f311b55e9e1bd8a10f9e807939c5686
4
+ data.tar.gz: 9268c65c42714ec98accf5e4a3f2bf36383a2c539e26850542e27b475fe93f12
5
5
  SHA512:
6
- metadata.gz: a8f4690f3a25c4169118b32560ab0f7bdc8d4199324bbff2b319582c736d4af2cd60233ce6278b3532f4bc64af348bc42ebe3e079c053a0997f49e60d9f3a9ea
7
- data.tar.gz: adbaa8e3ca6968e3fe257d628e4a335b3e65a189f45893c7418bc166c1e01ffa87417c11e2ee30e5e87f89ff1d849f025616856743f32a690665c6cbd1e1b593
6
+ metadata.gz: bf86b44edf7077e7d7ac6cc3c1af54379e3a5aaccfebced1a1b81aace9b1d6be2683b99d25cf8bf9e54492c0a14e405a003b93b5c4f522e9eb3839aabf6dbddb
7
+ data.tar.gz: 2778fbe72cbb71a5c2a4892f88b55dc01249a4f595ad4138eb15b7955c6ea09869ceae6f067d99ea1c5f92c3b7b0c0a5c045ae78c267321adfc66571c0b03c3f
data/.rubocop.yml CHANGED
@@ -38,6 +38,9 @@ Layout/MultilineAssignmentLayout:
38
38
  Layout/LineLength:
39
39
  Max: 180
40
40
 
41
+ Lint/IdentityComparison:
42
+ Enabled: false
43
+
41
44
  Lint/ConstantResolution:
42
45
  Enabled: false
43
46
 
data/README.md CHANGED
@@ -64,6 +64,7 @@ Referrers ----------------------------------------------------------------------
64
64
  * `interval` (default `30`): The interval in seconds for report.
65
65
  * `max_allocations` (default `10`): Outputs the specified number of objects that use a lot of memory.
66
66
  * `max_referrers` (default `3`): Outputs the number of references in order of the amount of memory used.
67
+ * `max_sample_objects` (default `100`): Sampling objects to detect referrer.
67
68
  * `logger` (defalut `nil`): Specify the logger object if you want to use custom logger.
68
69
  * `filename` (defalut `nil`): Specify the filename if you want to use custom filename.
69
70
 
@@ -3,6 +3,7 @@
3
3
  # rbs_inline: enabled
4
4
 
5
5
  require 'objspace'
6
+ require 'set'
6
7
 
7
8
  class LeakProfiler
8
9
  class Allocations
@@ -15,11 +16,12 @@ class LeakProfiler
15
16
  # @rbs interval: Integer
16
17
  # @rbs max_allocations: Integer
17
18
  # @rbs max_referrers: Integer
18
- def initialize(logger:, interval:, max_allocations:, max_referrers:)
19
+ def initialize(logger:, interval:, max_allocations:, max_referrers:, max_sample_objects:)
19
20
  @logger = logger
20
21
  @interval = interval
21
22
  @max_allocations = max_allocations
22
23
  @max_referrers = max_referrers
24
+ @max_sample_objects = max_sample_objects
23
25
  end
24
26
 
25
27
  def report
@@ -44,7 +46,12 @@ class LeakProfiler
44
46
  allocations[key][:metrics][:count] += 1
45
47
  allocations[key][:metrics][:bytes] += ObjectSpace.memsize_of(obj)
46
48
 
47
- allocations[key][:sample_object] = obj
49
+ allocations[key][:sample_objects] ||= []
50
+ allocations[key][:sample_objects] << obj
51
+ end
52
+
53
+ allocations.each_value do |v|
54
+ v[:sample_objects] = v[:sample_objects].sample(@max_sample_objects)
48
55
  end
49
56
 
50
57
  report_allocations_class(allocations_by_class)
@@ -88,7 +95,7 @@ class LeakProfiler
88
95
 
89
96
  objs = allocations.reject { |k, _| k == UNKNOWN }
90
97
  sort(objs).take(@max_referrers).each do |key, value|
91
- referrer_objects = detect_referrer_objects(value[:sample_object])
98
+ referrer_objects = detect_referrer_objects(value[:sample_objects])
92
99
 
93
100
  logs = referrer_objects.map do |r|
94
101
  klass = obj_class(r[:referrer_object])
@@ -102,12 +109,14 @@ class LeakProfiler
102
109
  end
103
110
  end
104
111
 
105
- def detect_referrer_objects(object)
112
+ def detect_referrer_objects(objects)
106
113
  referrer_objects = []
114
+ objects_ids = objects.to_set(&:object_id)
115
+
107
116
  ObjectSpace.each_object.each do |obj|
108
117
  r = ObjectSpace.reachable_objects_from(obj)
109
118
  begin
110
- if r&.any? { |o| o.equal?(object) }
119
+ if r&.any? { |o| objects_ids.include?(o.object_id) }
111
120
  key = allocated_location(obj)
112
121
  referrer_objects << { referrer_object: obj, referrer_object_allocated_line: key }
113
122
  end
@@ -21,13 +21,14 @@ class LeakProfiler
21
21
  # @rbs interval: Integer
22
22
  # @rbs max_allocations: Integer
23
23
  # @rbs max_referrers: Integer
24
+ # @rbs max_sample_objects: Integer
24
25
  # @rbs logger: untyped
25
26
  # @rbs filename: String
26
27
  # @rbs return: self
27
- def report(interval: 30, max_allocations: 10, max_referrers: 3, logger: nil, filename: nil)
28
+ def report(interval: 30, max_allocations: 10, max_referrers: 3, max_sample_objects: 100, logger: nil, filename: nil)
28
29
  filename ||= "leak_profiler-#{Process.pid}.log"
29
30
  logger ||= Logger.new(File.join(@output_dir, filename))
30
- profiler = LeakProfiler::Allocations.new(logger: logger, interval: interval, max_allocations: max_allocations, max_referrers: max_referrers)
31
+ profiler = LeakProfiler::Allocations.new(logger: logger, interval: interval, max_allocations: max_allocations, max_referrers: max_referrers, max_sample_objects: max_sample_objects)
31
32
  profiler.report
32
33
  @threads << profiler.thread
33
34
 
@@ -10,7 +10,7 @@ class LeakProfiler
10
10
  # @rbs interval: Integer
11
11
  # @rbs max_allocations: Integer
12
12
  # @rbs max_referrers: Integer
13
- def initialize: (logger: untyped, interval: Integer, max_allocations: Integer, max_referrers: Integer) -> untyped
13
+ def initialize: (logger: untyped, interval: Integer, max_allocations: Integer, max_referrers: Integer, max_sample_objects: untyped) -> untyped
14
14
 
15
15
  def report: () -> untyped
16
16
 
@@ -22,7 +22,7 @@ class LeakProfiler
22
22
 
23
23
  def report_referrer_objects: (untyped allocations) -> untyped
24
24
 
25
- def detect_referrer_objects: (untyped object) -> untyped
25
+ def detect_referrer_objects: (untyped objects) -> untyped
26
26
 
27
27
  def allocated_location: (untyped obj) -> untyped
28
28
 
@@ -8,10 +8,11 @@ class LeakProfiler
8
8
  # @rbs interval: Integer
9
9
  # @rbs max_allocations: Integer
10
10
  # @rbs max_referrers: Integer
11
+ # @rbs max_sample_objects: Integer
11
12
  # @rbs logger: untyped
12
13
  # @rbs filename: String
13
14
  # @rbs return: self
14
- def report: (?interval: Integer, ?max_allocations: Integer, ?max_referrers: Integer, ?logger: untyped, ?filename: String) -> self
15
+ def report: (?interval: Integer, ?max_allocations: Integer, ?max_referrers: Integer, ?max_sample_objects: Integer, ?logger: untyped, ?filename: String) -> self
15
16
 
16
17
  # @rbs interval: Integer
17
18
  # @rbs filename: String
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leak_profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.6
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Watson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-09-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: logger
@@ -58,7 +57,6 @@ metadata:
58
57
  homepage_uri: https://github.com/Watson1978/leak_profiler
59
58
  source_code_uri: https://github.com/Watson1978/leak_profiler
60
59
  rubygems_mfa_required: 'true'
61
- post_install_message:
62
60
  rdoc_options: []
63
61
  require_paths:
64
62
  - lib
@@ -73,8 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
71
  - !ruby/object:Gem::Version
74
72
  version: '0'
75
73
  requirements: []
76
- rubygems_version: 3.5.22
77
- signing_key:
74
+ rubygems_version: 3.6.9
78
75
  specification_version: 4
79
76
  summary: A simple profiler for Ruby to detect memory leak.
80
77
  test_files: []