class General
General process information.
Definitions
def as_json
Convert the object to a JSON serializable hash.
Implementation
def as_json
{
process_id: self.process_id,
parent_process_id: self.parent_process_id,
process_group_id: self.process_group_id,
processor_utilization: self.processor_utilization,
total_size: self.total_size,
virtual_size: self.virtual_size,
resident_size: self.resident_size,
processor_time: self.processor_time,
elapsed_time: self.elapsed_time,
command: self.command,
memory: self.memory&.as_json,
}
end
def to_json(*arguments)
Convert the object to a JSON string.
Implementation
def to_json(*arguments)
as_json.to_json(*arguments)
end
def total_size
The total size of the process in memory, in kilobytes.
Implementation
def total_size
if memory = self.memory
memory.proportional_size
else
self.resident_size
end
end
def self.expand_children(children, hierarchy, pids)
Recursively expand a set of child PIDs into a collection.
Signature
-
parameter
childrenArray<Integer> The list of child process IDs to expand.
-
parameter
hierarchyHash<Integer, Array<Integer>> The parent-to-children process hierarchy.
-
parameter
pidsSet<Integer> The set to populate with process IDs.
Implementation
def self.expand_children(children, hierarchy, pids)
children.each do |pid|
self.expand(pid, hierarchy, pids)
end
end
def self.expand(pid, hierarchy, pids)
Recursively expand a process and its descendants into a collection.
Signature
-
parameter
pidInteger The process ID to expand.
-
parameter
hierarchyHash<Integer, Array<Integer>> The parent-to-children process hierarchy.
-
parameter
pidsSet<Integer> The set to populate with process IDs.
Implementation
def self.expand(pid, hierarchy, pids)
unless pids.include?(pid)
pids << pid
if children = hierarchy.fetch(pid, nil)
self.expand_children(children, hierarchy, pids)
end
end
end
def self.build_tree(processes)
Build a parent-to-children process hierarchy from a set of processes.
Signature
-
parameter
processesHash<Integer, General> A hash mapping PIDs to General instances.
-
returns
Hash<Integer, Array<Integer>> A hash mapping each parent PID to an array of child PIDs.
Implementation
def self.build_tree(processes)
hierarchy = Hash.new{|h,k| h[k] = []}
processes.each_value do |process|
if parent_process_id = process.parent_process_id
hierarchy[parent_process_id] << process.process_id
end
end
return hierarchy
end
def self.capture_memory(processes)
Capture detailed memory metrics for each process in the given collection.
Signature
-
parameter
processesHash<Integer, General> A hash mapping PIDs to General instances.
Implementation
def self.capture_memory(processes)
count = processes.size
processes.each do |pid, process|
process.memory = Memory.capture(pid, count: count)
end
end
def self.capture(pid: nil, ppid: nil, ps: PS, memory: Memory.supported?)
Capture process information. If given a pid, it will capture the details of that process. If given a ppid, it will capture the details of all child processes. Specify both pid and ppid if you want to capture a process and all its children.
Signature
-
parameter
pidInteger The process ID to capture.
-
parameter
ppidInteger The parent process ID to capture.
Implementation
def self.capture(pid: nil, ppid: nil, ps: PS, memory: Memory.supported?)
input, output = IO.pipe
arguments = [ps]
if pid && ppid.nil?
arguments.push("-p", Array(pid).join(","))
else
arguments.push("ax")
end
arguments.push("-o", FIELDS.keys.join(","))
ps_pid = Process.spawn(*arguments, out: output, pgroup: true)
output.close
header, *lines = input.readlines.map(&:strip)
processes = {}
lines.map do |line|
record = FIELDS.
zip(line.split(/\s+/, FIELDS.size)).
map{|(key, type), value| type.call(value)}
instance = self.new(*record)
processes[instance.process_id] = instance
end
if ppid
pids = Set.new
hierarchy = self.build_tree(processes)
self.expand_children(Array(pid), hierarchy, pids)
self.expand_children(Array(ppid), hierarchy, pids)
processes.select! do |pid, process|
if pid != ps_pid
pids.include?(pid)
end
end
end
if memory
self.capture_memory(processes)
end
return processes
ensure
Process.wait(ps_pid) if ps_pid
end