diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2016-11-30 23:54:52 +0100 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2016-11-30 23:54:52 +0100 |
commit | 29496900f772c8c594fa9c5142a88a5291c05f55 (patch) | |
tree | a1d1031c89c18f34ffcab8796a4d37664814d8c5 | |
parent | 1bf2f41c446be2eb623945fae4fb760bd1188c3c (diff) | |
parent | 34c261da4995f6a4baf2142d59a4e879de89ea68 (diff) | |
download | psutil-29496900f772c8c594fa9c5142a88a5291c05f55.tar.gz |
Merge branch 'master' into 357-proc-cpu-num
-rw-r--r-- | HISTORY.rst | 3 | ||||
-rw-r--r-- | README.rst | 3 | ||||
-rw-r--r-- | docs/index.rst | 56 | ||||
-rw-r--r-- | psutil/__init__.py | 48 |
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 @@ -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: |