summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-11-30 23:54:52 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2016-11-30 23:54:52 +0100
commit29496900f772c8c594fa9c5142a88a5291c05f55 (patch)
treea1d1031c89c18f34ffcab8796a4d37664814d8c5
parent1bf2f41c446be2eb623945fae4fb760bd1188c3c (diff)
parent34c261da4995f6a4baf2142d59a4e879de89ea68 (diff)
downloadpsutil-29496900f772c8c594fa9c5142a88a5291c05f55.tar.gz
Merge branch 'master' into 357-proc-cpu-num
-rw-r--r--HISTORY.rst3
-rw-r--r--README.rst3
-rw-r--r--docs/index.rst56
-rw-r--r--psutil/__init__.py48
4 files changed, 79 insertions, 31 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index defd94d9..f93e0974 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -14,6 +14,9 @@
**Bug fixes**
- 936_: [Windows] fix compilation error on VS 2013 (patch by Max BĂ©langer).
+- 940_: [Linux] cpu_percent() and cpu_times_percent() was calculated
+ incorrectly as "iowait", "guest" and "guest_nice" times were not properly
+ taken into account.
5.0.0
diff --git a/README.rst b/README.rst
index fcdc8cd9..91d41cdb 100644
--- a/README.rst
+++ b/README.rst
@@ -247,9 +247,6 @@ Process management
[0, 1, 2, 3]
>>> p.cpu_affinity([0]) # set
>>>
- >>> p.memory_percent()
- 0.63423
- >>>
>>> p.memory_info()
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
diff --git a/docs/index.rst b/docs/index.rst
index 360ef158..a18bba81 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -61,21 +61,29 @@ CPU
Every attribute represents the seconds the CPU has spent in the given mode.
The attributes availability varies depending on the platform:
- - **user**
- - **system**
- - **idle**
+ - **user**: time spent by normal processes executing in user mode; on Linux
+ this also includes **guest** time
+ - **system**: time spent by processes executing in kernel mode
+ - **idle**: time spent doing nothing
Platform-specific fields:
- - **nice** *(UNIX)*
- - **iowait** *(Linux)*
- - **irq** *(Linux, BSD)*
- - **softirq** *(Linux)*
- - **steal** *(Linux 2.6.11+)*
- - **guest** *(Linux 2.6.24+)*
- - **guest_nice** *(Linux 3.2.0+)*
- - **interrupt** *(Windows)*
- - **dpc** *(Windows)*
+ - **nice** *(UNIX)*: time spent by niced processes executing in user mode;
+ on Linux this also includes **guest_nice** time
+ - **iowait** *(Linux)*: time spent waiting for I/O to complete
+ - **irq** *(Linux, BSD)*: time spent for servicing hardware interrupts
+ - **softirq** *(Linux)*: time spent for servicing software interrupts
+ - **steal** *(Linux 2.6.11+)*: time spent by other operating systems when
+ running in a virtualized environment
+ - **guest** *(Linux 2.6.24+)*: time spent running a virtual CPU for guest
+ operating systems under the control of the Linux kernel
+ - **guest_nice** *(Linux 3.2.0+)*: time spent running a niced guest
+ (virtual CPU for guest operating systems under the control of the Linux
+ kernel)
+ - **interrupt** *(Windows)*: time spent for servicing hardware interrupts (
+ similar to "irq" on UNIX)
+ - **dpc** *(Windows)*: time spent servicing deferred procedure calls (DPCs);
+ DPCs are interrupts that run at a lower priority than standard interrupts.
When *percpu* is ``True`` return a list of namedtuples for each logical CPU
on the system.
@@ -856,8 +864,8 @@ Process class
.. method:: name()
The process name. On Windows the return value is cached after first
- call. Not on POSIX because the process
- `name may change <https://github.com/giampaolo/psutil/issues/692>`__.
+ call. Not on POSIX because the process name
+ `may change <https://github.com/giampaolo/psutil/issues/692>`__.
.. method:: exe()
@@ -867,7 +875,8 @@ Process class
.. method:: cmdline()
- The command line this process has been called with.
+ The command line this process has been called with. The return value is not
+ cached because the cmdline of a process may change.
.. method:: environ()
@@ -1135,7 +1144,7 @@ Process class
multiple threads running on different CPU cores.
.. note::
- the returned value is explcitly **not** split evenly between all CPUs
+ the returned value is explicitly **not** split evenly between all CPUs
cores (differently from :func:`psutil.cpu_percent()`).
This means that a busy loop process running on a system with 2 CPU
cores will be reported as having 100% CPU utilization instead of 50%.
@@ -1157,9 +1166,12 @@ Process class
Get or set process current
`CPU affinity <http://www.linuxjournal.com/article/6799?page=0,0>`__.
CPU affinity consists in telling the OS to run a certain process on a
- limited set of CPUs only. The number of eligible CPUs can be obtained with
- ``list(range(psutil.cpu_count()))``. ``ValueError`` will be raise on set
- in case an invalid CPU number is specified.
+ limited set of CPUs only.
+ On Linux this is done via the ``taskset`` command.
+ The number of eligible CPUs can be obtained with
+ ``list(range(psutil.cpu_count()))``.
+ ``ValueError`` will be raised on set in case an invalid CPU number is
+ specified.
>>> import psutil
>>> psutil.cpu_count()
@@ -1274,7 +1286,7 @@ Process class
pmem(rss=15491072, vms=84025344, shared=5206016, text=2555904, lib=0, data=9891840, dirty=0)
.. versionchanged::
- 4.0.0 mutiple fields are returned, not only `rss` and `vms`.
+ 4.0.0 multiple fields are returned, not only `rss` and `vms`.
.. method:: memory_info_ex()
@@ -1294,7 +1306,7 @@ Process class
It does so by passing through the whole process address.
As such it usually requires higher user privileges than
:meth:`memory_info` and is considerably slower.
- On platforms where extra fields are not implented this simply returns the
+ On platforms where extra fields are not implemented this simply returns the
same metrics as :meth:`memory_info`.
- **uss** *(Linux, OSX, Windows)*:
@@ -1864,7 +1876,7 @@ Constants
Availability: Linux
.. versionchanged::
- 3.0.0 on Python >= 3.4 thse constants are
+ 3.0.0 on Python >= 3.4 these constants are
`enums <https://docs.python.org/3/library/enum.html#module-enum>`__
instead of a plain integer.
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 0ab33783..0ed28945 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -1015,7 +1015,8 @@ class Process(object):
return _timer() * num_cpus
else:
def timer():
- return sum(cpu_times())
+ t = cpu_times()
+ return sum((t.user, t.system))
if blocking:
st1 = timer()
@@ -1641,6 +1642,41 @@ except Exception:
traceback.print_exc()
+def _cpu_tot_time(times):
+ """Given a cpu_time() ntuple calculates the total CPU time
+ (including idle time).
+ """
+ tot = sum(times)
+ if LINUX:
+ # On Linux guest times are already accounted in "user" or
+ # "nice" times, so we subtract them from total.
+ # Htop does the same. References:
+ # https://github.com/giampaolo/psutil/pull/940
+ # http://unix.stackexchange.com/questions/178045
+ # https://github.com/torvalds/linux/blob/
+ # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/
+ # cputime.c#L158
+ tot -= getattr(times, "guest", 0) # Linux 2.6.24+
+ tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+
+ return tot
+
+
+def _cpu_busy_time(times):
+ """Given a cpu_time() ntuple calculates the busy CPU time.
+ We do so by subtracting all idle CPU times.
+ """
+ busy = _cpu_tot_time(times)
+ busy -= times.idle
+ # Linux: "iowait" is time during which the CPU does not do anything
+ # (waits for IO to complete). On Linux IO wait is *not* accounted
+ # in "idle" time so we subtract it. Htop does the same.
+ # References:
+ # https://github.com/torvalds/linux/blob/
+ # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244
+ busy -= getattr(times, "iowait", 0)
+ return busy
+
+
def cpu_percent(interval=None, percpu=False):
"""Return a float representing the current system-wide CPU
utilization as a percentage.
@@ -1683,11 +1719,11 @@ def cpu_percent(interval=None, percpu=False):
raise ValueError("interval is not positive (got %r)" % interval)
def calculate(t1, t2):
- t1_all = sum(t1)
- t1_busy = t1_all - t1.idle
+ t1_all = _cpu_tot_time(t1)
+ t1_busy = _cpu_busy_time(t1)
- t2_all = sum(t2)
- t2_busy = t2_all - t2.idle
+ t2_all = _cpu_tot_time(t2)
+ t2_busy = _cpu_busy_time(t2)
# this usually indicates a float precision issue
if t2_busy <= t1_busy:
@@ -1759,7 +1795,7 @@ def cpu_times_percent(interval=None, percpu=False):
def calculate(t1, t2):
nums = []
- all_delta = sum(t2) - sum(t1)
+ all_delta = _cpu_tot_time(t2) - _cpu_tot_time(t1)
for field in t1._fields:
field_delta = getattr(t2, field) - getattr(t1, field)
try: