leak_profiler 0.7.6 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f8b0c66ed134b82f8c7c4a5c1c19939962a8bd7cd2227df7e6e1fb695eaceb
4
- data.tar.gz: 5e0a015723cb449c3cf3154f7d47da2e7ef20e001c8ae3d3b8a2339699cb11c9
3
+ metadata.gz: 8f865010e37ad98c3d1dfc80fde69b7d3a32ef06a2166dca3c38d0829c7f17fe
4
+ data.tar.gz: 5939197c9c2824d56b3d520a8106c4070694f8a5ba66575eb021ea8223a2f8f8
5
5
  SHA512:
6
- metadata.gz: a8f4690f3a25c4169118b32560ab0f7bdc8d4199324bbff2b319582c736d4af2cd60233ce6278b3532f4bc64af348bc42ebe3e079c053a0997f49e60d9f3a9ea
7
- data.tar.gz: adbaa8e3ca6968e3fe257d628e4a335b3e65a189f45893c7418bc166c1e01ffa87417c11e2ee30e5e87f89ff1d849f025616856743f32a690665c6cbd1e1b593
6
+ metadata.gz: c4374a43ebbb3261281172d3ec46ba575c5707c82bca657501c5c3fe72dbae0ff3d384a5ce53179e7dd4d55e2aef256391c88484d7ea947da45477e7a06aa082
7
+ data.tar.gz: 91e28f5b4284598bb44ee9dde9306fbf2f6d46fe41a3ad3b7cce3c94d32315db249c8a6c427e0a9b01d76c73c196249efdc03aa23eea311811fac304764f2568
data/.rubocop.yml CHANGED
@@ -36,7 +36,10 @@ Layout/MultilineAssignmentLayout:
36
36
  Enabled: false
37
37
 
38
38
  Layout/LineLength:
39
- Max: 180
39
+ Enabled: false
40
+
41
+ Lint/IdentityComparison:
42
+ Enabled: false
40
43
 
41
44
  Lint/ConstantResolution:
42
45
  Enabled: false
data/README.md CHANGED
@@ -64,6 +64,8 @@ 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.
68
+ * `run_gc` (default `false`): Whether to invoke `GC.start` before logging to exclude temporary objects from the metrics.
67
69
  * `logger` (defalut `nil`): Specify the logger object if you want to use custom logger.
68
70
  * `filename` (defalut `nil`): Specify the filename if you want to use custom filename.
69
71
 
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ Rake::TestTask.new do |task|
14
14
  task.pattern = 'test/test_*.rb'
15
15
  end
16
16
 
17
- # Update RBS signature
17
+ desc 'Update RBS signature'
18
18
  task :'rbs:update' do
19
19
  sh 'bundle exec rbs-inline --output lib'
20
20
  end
@@ -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,15 @@ 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
+ # @rbs max_sample_objects: Integer
20
+ # @rbs run_gc: bool
21
+ def initialize(logger:, interval:, max_allocations:, max_referrers:, max_sample_objects:, run_gc: false)
19
22
  @logger = logger
20
23
  @interval = interval
21
24
  @max_allocations = max_allocations
22
25
  @max_referrers = max_referrers
26
+ @max_sample_objects = max_sample_objects
27
+ @run_gc = run_gc
23
28
  end
24
29
 
25
30
  def report
@@ -29,6 +34,8 @@ class LeakProfiler
29
34
  sleep(@interval)
30
35
  ObjectSpace.trace_object_allocations_stop
31
36
 
37
+ GC.start if @run_gc
38
+
32
39
  allocations = Hash.new { |h, k| h[k] = {} }
33
40
  allocations_by_class = Hash.new { |h, k| h[k] = 0 }
34
41
 
@@ -44,7 +51,12 @@ class LeakProfiler
44
51
  allocations[key][:metrics][:count] += 1
45
52
  allocations[key][:metrics][:bytes] += ObjectSpace.memsize_of(obj)
46
53
 
47
- allocations[key][:sample_object] = obj
54
+ allocations[key][:sample_objects] ||= []
55
+ allocations[key][:sample_objects] << obj
56
+ end
57
+
58
+ allocations.each_value do |v|
59
+ v[:sample_objects] = v[:sample_objects].sample(@max_sample_objects)
48
60
  end
49
61
 
50
62
  report_allocations_class(allocations_by_class)
@@ -88,7 +100,7 @@ class LeakProfiler
88
100
 
89
101
  objs = allocations.reject { |k, _| k == UNKNOWN }
90
102
  sort(objs).take(@max_referrers).each do |key, value|
91
- referrer_objects = detect_referrer_objects(value[:sample_object])
103
+ referrer_objects = detect_referrer_objects(value[:sample_objects])
92
104
 
93
105
  logs = referrer_objects.map do |r|
94
106
  klass = obj_class(r[:referrer_object])
@@ -102,12 +114,14 @@ class LeakProfiler
102
114
  end
103
115
  end
104
116
 
105
- def detect_referrer_objects(object)
117
+ def detect_referrer_objects(objects)
106
118
  referrer_objects = []
119
+ objects_ids = objects.to_set(&:object_id)
120
+
107
121
  ObjectSpace.each_object.each do |obj|
108
122
  r = ObjectSpace.reachable_objects_from(obj)
109
123
  begin
110
- if r&.any? { |o| o.equal?(object) }
124
+ if r&.any? { |o| objects_ids.include?(o.object_id) }
111
125
  key = allocated_location(obj)
112
126
  referrer_objects << { referrer_object: obj, referrer_object_allocated_line: key }
113
127
  end
@@ -21,13 +21,15 @@ 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
25
+ # @rbs run_gc: bool
24
26
  # @rbs logger: untyped
25
27
  # @rbs filename: String
26
28
  # @rbs return: self
27
- def report(interval: 30, max_allocations: 10, max_referrers: 3, logger: nil, filename: nil)
29
+ def report(interval: 30, max_allocations: 10, max_referrers: 3, max_sample_objects: 100, run_gc: false, logger: nil, filename: nil)
28
30
  filename ||= "leak_profiler-#{Process.pid}.log"
29
31
  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)
32
+ profiler = LeakProfiler::Allocations.new(logger: logger, interval: interval, max_allocations: max_allocations, max_referrers: max_referrers, max_sample_objects: max_sample_objects, run_gc: run_gc)
31
33
  profiler.report
32
34
  @threads << profiler.thread
33
35
 
@@ -10,7 +10,9 @@ 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
+ # @rbs max_sample_objects: Integer
14
+ # @rbs run_gc: bool
15
+ def initialize: (logger: untyped, interval: Integer, max_allocations: Integer, max_referrers: Integer, max_sample_objects: Integer, ?run_gc: bool) -> untyped
14
16
 
15
17
  def report: () -> untyped
16
18
 
@@ -22,7 +24,7 @@ class LeakProfiler
22
24
 
23
25
  def report_referrer_objects: (untyped allocations) -> untyped
24
26
 
25
- def detect_referrer_objects: (untyped object) -> untyped
27
+ def detect_referrer_objects: (untyped objects) -> untyped
26
28
 
27
29
  def allocated_location: (untyped obj) -> untyped
28
30
 
@@ -8,10 +8,12 @@ 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
12
+ # @rbs run_gc: bool
11
13
  # @rbs logger: untyped
12
14
  # @rbs filename: String
13
15
  # @rbs return: self
14
- def report: (?interval: Integer, ?max_allocations: Integer, ?max_referrers: Integer, ?logger: untyped, ?filename: String) -> self
16
+ def report: (?interval: Integer, ?max_allocations: Integer, ?max_referrers: Integer, ?max_sample_objects: Integer, ?run_gc: bool, ?logger: untyped, ?filename: String) -> self
15
17
 
16
18
  # @rbs interval: Integer
17
19
  # @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.1
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: 4.0.4
78
75
  specification_version: 4
79
76
  summary: A simple profiler for Ruby to detect memory leak.
80
77
  test_files: []