diff --git a/HISTORY.rst b/HISTORY.rst index 870f351b2..8bc3f7847 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -10,7 +10,7 @@ - 1173_: introduced PSUTIL_DEBUG environment variable which can be set in order to print useful debug messages on stderr (useful in case of nasty errors). - 1177_: added support for sensors_battery() on OSX. (patch by Arnon Yaari) -- 1183_: Process.children() is around 2.2x faster on UNIX. +- 1183_: Process.children() is 2x faster on UNIX and 2.4x faster on Linux. **Bug fixes** diff --git a/psutil/__init__.py b/psutil/__init__.py index 605bd7687..98e608708 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -255,11 +255,11 @@ if hasattr(_psplatform, 'ppid_map'): - # Windows only (C). + # Faster version (Windows and Linux). _ppid_map = _psplatform.ppid_map else: def _ppid_map(): - """Obtain a {pid: ppid, ...} dict for all running processes in + """Return a {pid: ppid, ...} dict for all running processes in one shot. Used to speed up Process.children(). """ ret = {} diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index a5a3fd891..5076b4b7a 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -1356,6 +1356,27 @@ def pid_exists(pid): return pid in pids() +def ppid_map(): + """Obtain a {pid: ppid, ...} dict for all running processes in + one shot. Used to speed up Process.children(). + """ + ret = {} + procfs_path = get_procfs_path() + for pid in pids(): + try: + with open_binary("%s/%s/stat" % (procfs_path, pid)) as f: + data = f.read() + except EnvironmentError as err: + if err.errno not in (errno.ENOENT, errno.EPERM, errno.EACCES): + raise + else: + rpar = data.rfind(b')') + dset = data[rpar + 2:].split() + ppid = int(dset[1]) + ret[pid] = ppid + return ret + + def wrap_exceptions(fun): """Decorator which translates bare OSError and IOError exceptions into NoSuchProcess and AccessDenied.