class Cluster
Detects memory leaks in a cluster of processes.
This class is used to manage a cluster of processes and detect memory leaks in each process. It can also enforce cluster-wide memory limits in two ways:
-
Total Size Limit (
total_size_limit): Limits the total memory used by all processes in the cluster, calculated as max(shared memory) + sum(private memory). -
Free Size Minimum (
free_size_minimum): Ensures the host system maintains a minimum amount of free memory by terminating processes when free memory drops too low.
Both limits can be active simultaneously. Processes are terminated in order of largest private memory first to maximize the impact of each termination.
Definitions
def initialize(total_size_limit: nil, free_size_minimum: nil)
Create a new cluster.
Signature
-
parameter
total_size_limitNumeric | Nil The total memory limit for the cluster.
-
parameter
free_size_minimumNumeric | Nil The minimum free memory required on the host, in bytes.
Implementation
def initialize(total_size_limit: nil, free_size_minimum: nil)
@total_size = nil
@total_size_limit = total_size_limit
@free_size_minimum = free_size_minimum
@processes = {}
end
def as_json(...)
Signature
-
returns
Hash A serializable representation of the cluster.
Implementation
def as_json(...)
{
total_size: @total_size,
total_size_limit: @total_size_limit,
free_size_minimum: @free_size_minimum,
processes: @processes.transform_values(&:as_json),
}
end
def to_json(...)
Signature
-
returns
String The JSON representation of the cluster.
Implementation
def to_json(...)
as_json.to_json(...)
end
attr :total_size
Signature
-
attribute
Numeric | Nil The total size of the cluster.
attr_accessor :total_size_limit
Signature
-
attribute
Numeric | Nil The total size limit for the cluster, in bytes, if which is exceeded, the cluster will terminate processes.
attr_accessor :free_size_minimum
Signature
-
attribute
Numeric | Nil The minimum free memory required on the host, in bytes. If free memory falls below this minimum, the cluster will terminate processes.
attr :processes
Signature
-
attribute
Hash(Integer, Monitor) The process IDs and monitors in the cluster.
def add(process_id, **options)
Add a new process ID to the cluster.
Implementation
def add(process_id, **options)
@processes[process_id] = Monitor.new(process_id, **options)
end
def remove(process_id)
Remove a process ID from the cluster.
Implementation
def remove(process_id)
@processes.delete(process_id)
end
def sample!
Sample the memory usage of all processes in the cluster.
Implementation
def sample!
@processes.each_value(&:sample!)
end
def check!(&block)
Check all processes in the cluster for memory leaks.
Signature
-
yields
{|process_id, monitor| ...} each process ID and monitor that is leaking or exceeds the memory limit.
Implementation
def check!(&block)
self.sample!
leaking = []
@processes.each do |process_id, monitor|
if monitor.leaking?
Console.debug(self, "Memory Leak Detected!", process_id: process_id, monitor: monitor)
leaking << [process_id, monitor]
end
end
if block_given?
leaking.each(&block)
# Finally, enforce any per-cluster memory limits:
if @total_size_limit
enforce_total_size_limit!(@total_size_limit, &block)
end
# Enforce minimum free memory requirement:
if @free_size_minimum
enforce_free_size_minimum!(@free_size_minimum, &block)
end
end
return leaking
end