summaryrefslogtreecommitdiffstats
path: root/import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py')
-rw-r--r--import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py292
1 files changed, 0 insertions, 292 deletions
diff --git a/import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py b/import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py
deleted file mode 100644
index cf88110b1..000000000
--- a/import-layers/yocto-poky/scripts/pybootchartgui/pybootchartgui/process_tree.py
+++ /dev/null
@@ -1,292 +0,0 @@
-# This file is part of pybootchartgui.
-
-# pybootchartgui is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# pybootchartgui is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with pybootchartgui. If not, see <http://www.gnu.org/licenses/>.
-
-class ProcessTree:
- """ProcessTree encapsulates a process tree. The tree is built from log files
- retrieved during the boot process. When building the process tree, it is
- pruned and merged in order to be able to visualize it in a comprehensible
- manner.
-
- The following pruning techniques are used:
-
- * idle processes that keep running during the last process sample
- (which is a heuristic for a background processes) are removed,
- * short-lived processes (i.e. processes that only live for the
- duration of two samples or less) are removed,
- * the processes used by the boot logger are removed,
- * exploders (i.e. processes that are known to spawn huge meaningless
- process subtrees) have their subtrees merged together,
- * siblings (i.e. processes with the same command line living
- concurrently -- thread heuristic) are merged together,
- * process runs (unary trees with processes sharing the command line)
- are merged together.
-
- """
- LOGGER_PROC = 'bootchart-colle'
- EXPLODER_PROCESSES = set(['hwup'])
-
- def __init__(self, writer, kernel, psstats, sample_period,
- monitoredApp, prune, idle, taskstats,
- accurate_parentage, for_testing = False):
- self.writer = writer
- self.process_tree = []
- self.taskstats = taskstats
- if psstats is None:
- process_list = kernel
- elif kernel is None:
- process_list = psstats.process_map.values()
- else:
- process_list = list(kernel) + list(psstats.process_map.values())
- self.process_list = sorted(process_list, key = lambda p: p.pid)
- self.sample_period = sample_period
-
- self.build()
- if not accurate_parentage:
- self.update_ppids_for_daemons(self.process_list)
-
- self.start_time = self.get_start_time(self.process_tree)
- self.end_time = self.get_end_time(self.process_tree)
- self.duration = self.end_time - self.start_time
- self.idle = idle
-
- if for_testing:
- return
-
- removed = self.merge_logger(self.process_tree, self.LOGGER_PROC, monitoredApp, False)
- writer.status("merged %i logger processes" % removed)
-
- if prune:
- p_processes = self.prune(self.process_tree, None)
- p_exploders = self.merge_exploders(self.process_tree, self.EXPLODER_PROCESSES)
- p_threads = self.merge_siblings(self.process_tree)
- p_runs = self.merge_runs(self.process_tree)
- writer.status("pruned %i process, %i exploders, %i threads, and %i runs" % (p_processes, p_exploders, p_threads, p_runs))
-
- self.sort(self.process_tree)
-
- self.start_time = self.get_start_time(self.process_tree)
- self.end_time = self.get_end_time(self.process_tree)
- self.duration = self.end_time - self.start_time
-
- self.num_proc = self.num_nodes(self.process_tree)
-
- def build(self):
- """Build the process tree from the list of top samples."""
- self.process_tree = []
- for proc in self.process_list:
- if not proc.parent:
- self.process_tree.append(proc)
- else:
- proc.parent.child_list.append(proc)
-
- def sort(self, process_subtree):
- """Sort process tree."""
- for p in process_subtree:
- p.child_list.sort(key = lambda p: p.pid)
- self.sort(p.child_list)
-
- def num_nodes(self, process_list):
- "Counts the number of nodes in the specified process tree."""
- nodes = 0
- for proc in process_list:
- nodes = nodes + self.num_nodes(proc.child_list)
- return nodes + len(process_list)
-
- def get_start_time(self, process_subtree):
- """Returns the start time of the process subtree. This is the start
- time of the earliest process.
-
- """
- if not process_subtree:
- return 100000000
- return min( [min(proc.start_time, self.get_start_time(proc.child_list)) for proc in process_subtree] )
-
- def get_end_time(self, process_subtree):
- """Returns the end time of the process subtree. This is the end time
- of the last collected sample.
-
- """
- if not process_subtree:
- return -100000000
- return max( [max(proc.start_time + proc.duration, self.get_end_time(proc.child_list)) for proc in process_subtree] )
-
- def get_max_pid(self, process_subtree):
- """Returns the max PID found in the process tree."""
- if not process_subtree:
- return -100000000
- return max( [max(proc.pid, self.get_max_pid(proc.child_list)) for proc in process_subtree] )
-
- def update_ppids_for_daemons(self, process_list):
- """Fedora hack: when loading the system services from rc, runuser(1)
- is used. This sets the PPID of all daemons to 1, skewing
- the process tree. Try to detect this and set the PPID of
- these processes the PID of rc.
-
- """
- rcstartpid = -1
- rcendpid = -1
- rcproc = None
- for p in process_list:
- if p.cmd == "rc" and p.ppid // 1000 == 1:
- rcproc = p
- rcstartpid = p.pid
- rcendpid = self.get_max_pid(p.child_list)
- if rcstartpid != -1 and rcendpid != -1:
- for p in process_list:
- if p.pid > rcstartpid and p.pid < rcendpid and p.ppid // 1000 == 1:
- p.ppid = rcstartpid
- p.parent = rcproc
- for p in process_list:
- p.child_list = []
- self.build()
-
- def prune(self, process_subtree, parent):
- """Prunes the process tree by removing idle processes and processes
- that only live for the duration of a single top sample. Sibling
- processes with the same command line (i.e. threads) are merged
- together. This filters out sleepy background processes, short-lived
- processes and bootcharts' analysis tools.
- """
- def is_idle_background_process_without_children(p):
- process_end = p.start_time + p.duration
- return not p.active and \
- process_end >= self.start_time + self.duration and \
- p.start_time > self.start_time and \
- p.duration > 0.9 * self.duration and \
- self.num_nodes(p.child_list) == 0
-
- num_removed = 0
- idx = 0
- while idx < len(process_subtree):
- p = process_subtree[idx]
- if parent != None or len(p.child_list) == 0:
-
- prune = False
- if is_idle_background_process_without_children(p):
- prune = True
- elif p.duration <= 2 * self.sample_period:
- # short-lived process
- prune = True
-
- if prune:
- process_subtree.pop(idx)
- for c in p.child_list:
- process_subtree.insert(idx, c)
- num_removed += 1
- continue
- else:
- num_removed += self.prune(p.child_list, p)
- else:
- num_removed += self.prune(p.child_list, p)
- idx += 1
-
- return num_removed
-
- def merge_logger(self, process_subtree, logger_proc, monitored_app, app_tree):
- """Merges the logger's process subtree. The logger will typically
- spawn lots of sleep and cat processes, thus polluting the
- process tree.
-
- """
- num_removed = 0
- for p in process_subtree:
- is_app_tree = app_tree
- if logger_proc == p.cmd and not app_tree:
- is_app_tree = True
- num_removed += self.merge_logger(p.child_list, logger_proc, monitored_app, is_app_tree)
- # don't remove the logger itself
- continue
-
- if app_tree and monitored_app != None and monitored_app == p.cmd:
- is_app_tree = False
-
- if is_app_tree:
- for child in p.child_list:
- self.merge_processes(p, child)
- num_removed += 1
- p.child_list = []
- else:
- num_removed += self.merge_logger(p.child_list, logger_proc, monitored_app, is_app_tree)
- return num_removed
-
- def merge_exploders(self, process_subtree, processes):
- """Merges specific process subtrees (used for processes which usually
- spawn huge meaningless process trees).
-
- """
- num_removed = 0
- for p in process_subtree:
- if processes in processes and len(p.child_list) > 0:
- subtreemap = self.getProcessMap(p.child_list)
- for child in subtreemap.values():
- self.merge_processes(p, child)
- num_removed += len(subtreemap)
- p.child_list = []
- p.cmd += " (+)"
- else:
- num_removed += self.merge_exploders(p.child_list, processes)
- return num_removed
-
- def merge_siblings(self, process_subtree):
- """Merges thread processes. Sibling processes with the same command
- line are merged together.
-
- """
- num_removed = 0
- idx = 0
- while idx < len(process_subtree)-1:
- p = process_subtree[idx]
- nextp = process_subtree[idx+1]
- if nextp.cmd == p.cmd:
- process_subtree.pop(idx+1)
- idx -= 1
- num_removed += 1
- p.child_list.extend(nextp.child_list)
- self.merge_processes(p, nextp)
- num_removed += self.merge_siblings(p.child_list)
- idx += 1
- if len(process_subtree) > 0:
- p = process_subtree[-1]
- num_removed += self.merge_siblings(p.child_list)
- return num_removed
-
- def merge_runs(self, process_subtree):
- """Merges process runs. Single child processes which share the same
- command line with the parent are merged.
-
- """
- num_removed = 0
- idx = 0
- while idx < len(process_subtree):
- p = process_subtree[idx]
- if len(p.child_list) == 1 and p.child_list[0].cmd == p.cmd:
- child = p.child_list[0]
- p.child_list = list(child.child_list)
- self.merge_processes(p, child)
- num_removed += 1
- continue
- num_removed += self.merge_runs(p.child_list)
- idx += 1
- return num_removed
-
- def merge_processes(self, p1, p2):
- """Merges two process' samples."""
- p1.samples.extend(p2.samples)
- p1.samples.sort( key = lambda p: p.time )
- p1time = p1.start_time
- p2time = p2.start_time
- p1.start_time = min(p1time, p2time)
- pendtime = max(p1time + p1.duration, p2time + p2.duration)
- p1.duration = pendtime - p1.start_time
OpenPOWER on IntegriCloud