Skip to content

Commit

Permalink
fix #976 / windows / io_counters(): add 2 new fields
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Feb 14, 2017
1 parent 9333bed commit 57745cf
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 23 deletions.
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
**Enhancements**

- 971_: [Linux] Add psutil.sensors_fans() function. (patch by Nicolas Hennion)
- 976_: [Windows] Process.io_counters() has 2 new fields: *other_count* and
*other_bytes*.

5.1.3
=====
Expand Down
22 changes: 16 additions & 6 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1213,13 +1213,20 @@ Process class

.. method:: io_counters()

Return process I/O statistics as a named tuple including the number of read
and write operations performed by the process and the amount of bytes read
and written (cumulative). For Linux you can refer to
Return process I/O statistics as a named tuple.
For Linux you can refer to
`/proc filesysem documentation <https://www.kernel.org/doc/Documentation/filesystems/proc.txt>`__.
On BSD there's apparently no way to retrieve bytes counters, hence ``-1``
is returned for **read_bytes** and **write_bytes** fields. OSX is not
supported.

- **read_count**: the number of read operations performed (cumulative).
- **write_count**: the number of write operations performed (cumulative).
- **read_bytes**: the number of bytes read (cumulative).
Always ``-1`` on BSD.
- **write_bytes**: the number of bytes written (cumulative).
Always ``-1`` on BSD.
- **other_count** *(Windows)*: the number of I/O operations performed,
other than read and write operations.
- **other_bytes** *(Windows)*: the number of bytes transferred during
operations other than read and write operations.

>>> import psutil
>>> p = psutil.Process()
Expand All @@ -1228,6 +1235,9 @@ Process class

Availability: all platforms except OSX and Solaris

.. versionchanged:: 5.2.0 added *other_count* and *other_bytes* Windows
metrics.

.. method:: num_ctx_switches()

The number voluntary and involuntary context switches performed by
Expand Down
13 changes: 9 additions & 4 deletions psutil/_psutil_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -2101,11 +2101,13 @@ psutil_proc_io_counters(PyObject *self, PyObject *args) {
return PyErr_SetFromWindowsErr(0);
}
CloseHandle(hProcess);
return Py_BuildValue("(KKKK)",
return Py_BuildValue("(KKKKKK)",
IoCounters.ReadOperationCount,
IoCounters.WriteOperationCount,
IoCounters.ReadTransferCount,
IoCounters.WriteTransferCount);
IoCounters.WriteTransferCount,
IoCounters.OtherOperationCount,
IoCounters.OtherTransferCount);
}


Expand Down Expand Up @@ -2793,20 +2795,23 @@ psutil_proc_info(PyObject *self, PyObject *args) {

py_retlist = Py_BuildValue(
#if defined(_WIN64)
"kkdddiKKKK" "kKKKKKKKKK",
"kkdddiKKKKKK" "kKKKKKKKKK",
#else
"kkdddiKKKK" "kIIIIIIIII",
"kkdddiKKKKKK" "kIIIIIIIII",
#endif
process->HandleCount, // num handles
ctx_switches, // num ctx switches
user_time, // cpu user time
kernel_time, // cpu kernel time
(double)create_time, // create time
(int)process->NumberOfThreads, // num threads
// IO counters
process->ReadOperationCount.QuadPart, // io rcount
process->WriteOperationCount.QuadPart, // io wcount
process->ReadTransferCount.QuadPart, // io rbytes
process->WriteTransferCount.QuadPart, // io wbytes
process->OtherOperationCount.QuadPart, // io others count
process->OtherTransferCount.QuadPart, // io others bytes
// memory
process->PageFaultCount, // num page faults
process->PeakWorkingSetSize, // peak wset
Expand Down
30 changes: 19 additions & 11 deletions psutil/_pswindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,18 @@ class Priority(enum.IntEnum):
io_wcount=7,
io_rbytes=8,
io_wbytes=9,
num_page_faults=10,
peak_wset=11,
wset=12,
peak_paged_pool=13,
paged_pool=14,
peak_non_paged_pool=15,
non_paged_pool=16,
pagefile=17,
peak_pagefile=18,
mem_private=19,
io_count_others=10,
io_bytes_others=11,
num_page_faults=12,
peak_wset=13,
wset=14,
peak_paged_pool=15,
paged_pool=16,
peak_non_paged_pool=17,
non_paged_pool=18,
pagefile=19,
peak_pagefile=20,
mem_private=21,
)


Expand All @@ -154,6 +156,10 @@ class Priority(enum.IntEnum):
'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time',
'create_time', 'num_threads', 'io_rcount', 'io_wcount',
'io_rbytes', 'io_wbytes'])
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'other_count', 'other_bytes'])


# =====================================================================
Expand Down Expand Up @@ -900,10 +906,12 @@ def io_counters(self):
info[pinfo_map['io_wcount']],
info[pinfo_map['io_rbytes']],
info[pinfo_map['io_wbytes']],
info[pinfo_map['io_count_others']],
info[pinfo_map['io_bytes_others']],
)
else:
raise
return _common.pio(*ret)
return pio(*ret)

@wrap_exceptions
def status(self):
Expand Down
4 changes: 4 additions & 0 deletions psutil/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ def test_io_counters(self):
assert io2.write_bytes >= io1.write_bytes, (io1, io2)
assert io2.read_count >= io1.read_count, (io1, io2)
assert io2.read_bytes >= io1.read_bytes, (io1, io2)
# sanity check
for i in range(len(io2)):
self.assertGreaterEqual(io2[i], 0)
self.assertGreaterEqual(io2[i], 0)

@unittest.skipUnless(LINUX or (WINDOWS and get_winver() >= WIN_VISTA),
'platform not supported')
Expand Down
6 changes: 4 additions & 2 deletions psutil/tests/test_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ def test_io_counters(self):
psutil_value.read_bytes, sys_value['ReadTransferCount'])
self.assertEqual(
psutil_value.write_bytes, sys_value['WriteTransferCount'])
self.assertEqual(
psutil_value.other_count, sys_value['OtherOperationCount'])
self.assertEqual(
psutil_value.other_bytes, sys_value['OtherTransferCount'])

def test_num_handles(self):
import ctypes
Expand Down Expand Up @@ -610,8 +614,6 @@ def test_io_counters(self):
side_effect=OSError(errno.EPERM, "msg")) as fun:
io_counters_2 = psutil.Process(self.pid).io_counters()
for i in range(len(io_counters_1)):
self.assertGreaterEqual(io_counters_1[i], 0)
self.assertGreaterEqual(io_counters_2[i], 0)
self.assertAlmostEqual(
io_counters_1[i], io_counters_2[i], delta=5)
assert fun.called
Expand Down

0 comments on commit 57745cf

Please sign in to comment.