mirror of https://github.com/python/cpython
Patch #512005: getrusage() returns struct-like object.
This commit is contained in:
parent
6cca2f48ed
commit
688357e035
|
@ -133,50 +133,56 @@ not be available from this module on that platform.
|
||||||
|
|
||||||
\subsection{Resource Usage}
|
\subsection{Resource Usage}
|
||||||
|
|
||||||
These functiona are used to retrieve resource usage information:
|
These functions are used to retrieve resource usage information:
|
||||||
|
|
||||||
\begin{funcdesc}{getrusage}{who}
|
\begin{funcdesc}{getrusage}{who}
|
||||||
This function returns a large tuple that describes the resources
|
This function returns an object that describes the resources
|
||||||
consumed by either the current process or its children, as specified
|
consumed by either the current process or its children, as specified
|
||||||
by the \var{who} parameter. The \var{who} parameter should be
|
by the \var{who} parameter. The \var{who} parameter should be
|
||||||
specified using one of the \constant{RUSAGE_*} constants described
|
specified using one of the \constant{RUSAGE_*} constants described
|
||||||
below.
|
below.
|
||||||
|
|
||||||
The elements of the return value each
|
The fields of the return value each describe how a particular system
|
||||||
describe how a particular system resource has been used, e.g. amount
|
resource has been used, e.g. amount of time spent running is user mode
|
||||||
of time spent running is user mode or number of times the process was
|
or number of times the process was swapped out of main memory. Some
|
||||||
swapped out of main memory. Some values are dependent on the clock
|
values are dependent on the clock tick internal, e.g. the amount of
|
||||||
tick internal, e.g. the amount of memory the process is using.
|
memory the process is using.
|
||||||
|
|
||||||
The first two elements of the return value are floating point values
|
For backward compatibility, the return value is also accessible as
|
||||||
representing the amount of time spent executing in user mode and the
|
a tuple of 16 elements.
|
||||||
amount of time spent executing in system mode, respectively. The
|
|
||||||
remaining values are integers. Consult the \manpage{getrusage}{2}
|
|
||||||
man page for detailed information about these values. A brief
|
|
||||||
summary is presented here:
|
|
||||||
|
|
||||||
\begin{tableii}{r|l}{code}{Offset}{Resource}
|
The fields \member{ru_utime} and \member{ru_stime} of the return value
|
||||||
\lineii{0}{time in user mode (float)}
|
are floating point values representing the amount of time spent
|
||||||
\lineii{1}{time in system mode (float)}
|
executing in user mode and the amount of time spent executing in system
|
||||||
\lineii{2}{maximum resident set size}
|
mode, respectively. The remaining values are integers. Consult the
|
||||||
\lineii{3}{shared memory size}
|
\manpage{getrusage}{2} man page for detailed information about these
|
||||||
\lineii{4}{unshared memory size}
|
values. A brief summary is presented here:
|
||||||
\lineii{5}{unshared stack size}
|
|
||||||
\lineii{6}{page faults not requiring I/O}
|
\begin{tableiii}{r|l|l}{code}{Index}{Field}{Resource}
|
||||||
\lineii{7}{page faults requiring I/O}
|
\lineiii{0}{\member{ru_utime}}{time in user mode (float)}
|
||||||
\lineii{8}{number of swap outs}
|
\lineiii{1}{\member{ru_stime}}{time in system mode (float)}
|
||||||
\lineii{9}{block input operations}
|
\lineiii{2}{\member{ru_maxrss}}{maximum resident set size}
|
||||||
\lineii{10}{block output operations}
|
\lineiii{3}{\member{ru_ixrss}}{shared memory size}
|
||||||
\lineii{11}{messages sent}
|
\lineiii{4}{\member{ru_idrss}}{unshared memory size}
|
||||||
\lineii{12}{messages received}
|
\lineiii{5}{\member{ru_isrss}}{unshared stack size}
|
||||||
\lineii{13}{signals received}
|
\lineiii{6}{\member{ru_minflt}}{page faults not requiring I/O}
|
||||||
\lineii{14}{voluntary context switches}
|
\lineiii{7}{\member{ru_majflt}}{page faults requiring I/O}
|
||||||
\lineii{15}{involuntary context switches}
|
\lineiii{8}{\member{ru_nswap}}{number of swap outs}
|
||||||
\end{tableii}
|
\lineiii{9}{\member{ru_inblock}}{block input operations}
|
||||||
|
\lineiii{10}{\member{ru_oublock}}{block output operations}
|
||||||
|
\lineiii{11}{\member{ru_msgsnd}}{messages sent}
|
||||||
|
\lineiii{12}{\member{ru_msgrcv}}{messages received}
|
||||||
|
\lineiii{13}{\member{ru_nsignals}}{signals received}
|
||||||
|
\lineiii{14}{\member{ru_nvcsw}}{voluntary context switches}
|
||||||
|
\lineiii{15}{\member{ru_nivcsw}}{involuntary context switches}
|
||||||
|
\end{tableiii}
|
||||||
|
|
||||||
This function will raise a \exception{ValueError} if an invalid
|
This function will raise a \exception{ValueError} if an invalid
|
||||||
\var{who} parameter is specified. It may also raise
|
\var{who} parameter is specified. It may also raise
|
||||||
\exception{error} exception in unusual circumstances.
|
\exception{error} exception in unusual circumstances.
|
||||||
|
|
||||||
|
\versionchanged[Added access to values as attributes of the
|
||||||
|
returned object]{2.3}
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{getpagesize}{}
|
\begin{funcdesc}{getpagesize}{}
|
||||||
|
|
|
@ -413,6 +413,7 @@ Joel Shprentz
|
||||||
Itamar Shtull-Trauring
|
Itamar Shtull-Trauring
|
||||||
Eric Siegerman
|
Eric Siegerman
|
||||||
Paul Sijben
|
Paul Sijben
|
||||||
|
Kirill Simonov
|
||||||
Nathan Paul Simons
|
Nathan Paul Simons
|
||||||
Janne Sinkkonen
|
Janne Sinkkonen
|
||||||
George Sipe
|
George Sipe
|
||||||
|
|
|
@ -56,7 +56,8 @@ Extension modules
|
||||||
hole was quickly plugged in zlib-1.1.4, and the Windows build of
|
hole was quickly plugged in zlib-1.1.4, and the Windows build of
|
||||||
Python now ships with zlib-1.1.4.
|
Python now ships with zlib-1.1.4.
|
||||||
|
|
||||||
- pwd and grp return enhanced tuples now, with symbolic field names.
|
- pwd, grp, and resource return enhanced tuples now, with symbolic
|
||||||
|
field names.
|
||||||
|
|
||||||
- array.array is now a type object. A new format character
|
- array.array is now a type object. A new format character
|
||||||
'u' indicates Py_UNICODE arrays. For those, .tounicode and
|
'u' indicates Py_UNICODE arrays. For those, .tounicode and
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "structseq.h"
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -16,11 +17,48 @@
|
||||||
|
|
||||||
static PyObject *ResourceError;
|
static PyObject *ResourceError;
|
||||||
|
|
||||||
|
static char struct_rusage__doc__[] =
|
||||||
|
"struct_rusage: Result from getrusage.\n\n"
|
||||||
|
"This object may be accessed either as a tuple of\n"
|
||||||
|
" (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n"
|
||||||
|
" nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n"
|
||||||
|
"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.\n";
|
||||||
|
|
||||||
|
static PyStructSequence_Field struct_rusage_fields[] = {
|
||||||
|
{"ru_utime", "user time used"},
|
||||||
|
{"ru_stime", "system time used"},
|
||||||
|
{"ru_maxrss", "max. resident set size"},
|
||||||
|
{"ru_ixrss", "shared memory size"},
|
||||||
|
{"ru_idrss", "unshared data size"},
|
||||||
|
{"ru_isrss", "unshared stack size"},
|
||||||
|
{"ru_minflt", "page faults not requiring I/O"},
|
||||||
|
{"ru_majflt", "page faults requiring I/O"},
|
||||||
|
{"ru_nswap", "number of swap outs"},
|
||||||
|
{"ru_inblock", "block input operations"},
|
||||||
|
{"ru_oublock", "block output operations"},
|
||||||
|
{"ru_msgsnd", "IPC messages sent"},
|
||||||
|
{"ru_msgrcv", "IPC messages received"},
|
||||||
|
{"ru_nsignals", "signals received"},
|
||||||
|
{"ru_nvcsw", "voluntary context switches"},
|
||||||
|
{"ru_nivcsw", "involuntary context switches"},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyStructSequence_Desc struct_rusage_desc = {
|
||||||
|
"resource.struct_rusage", /* name */
|
||||||
|
struct_rusage__doc__, /* doc */
|
||||||
|
struct_rusage_fields, /* fields */
|
||||||
|
16 /* n_in_sequence */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject StructRUsageType;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
resource_getrusage(PyObject *self, PyObject *args)
|
resource_getrusage(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int who;
|
int who;
|
||||||
struct rusage ru;
|
struct rusage ru;
|
||||||
|
PyObject *result;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i:getrusage", &who))
|
if (!PyArg_ParseTuple(args, "i:getrusage", &who))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -35,29 +73,35 @@ resource_getrusage(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Yeah, this 16-tuple is way ugly. It's probably a lot less
|
result = PyStructSequence_New(&StructRUsageType);
|
||||||
ugly than a dictionary with keys (or object attributes)
|
if (!result)
|
||||||
named things like 'ixrss'.
|
return NULL;
|
||||||
*/
|
|
||||||
return Py_BuildValue(
|
PyStructSequence_SET_ITEM(result, 0,
|
||||||
"ddiiiiiiiiiiiiii",
|
PyFloat_FromDouble(doubletime(ru.ru_utime)));
|
||||||
doubletime(ru.ru_utime), /* user time used */
|
PyStructSequence_SET_ITEM(result, 1,
|
||||||
doubletime(ru.ru_stime), /* system time used */
|
PyFloat_FromDouble(doubletime(ru.ru_stime)));
|
||||||
ru.ru_maxrss, /* max. resident set size */
|
PyStructSequence_SET_ITEM(result, 2, PyInt_FromLong(ru.ru_maxrss));
|
||||||
ru.ru_ixrss, /* shared memory size */
|
PyStructSequence_SET_ITEM(result, 3, PyInt_FromLong(ru.ru_ixrss));
|
||||||
ru.ru_idrss, /* unshared memory size */
|
PyStructSequence_SET_ITEM(result, 4, PyInt_FromLong(ru.ru_idrss));
|
||||||
ru.ru_isrss, /* unshared stack size */
|
PyStructSequence_SET_ITEM(result, 5, PyInt_FromLong(ru.ru_isrss));
|
||||||
ru.ru_minflt, /* page faults not requiring I/O*/
|
PyStructSequence_SET_ITEM(result, 6, PyInt_FromLong(ru.ru_minflt));
|
||||||
ru.ru_majflt, /* page faults requiring I/O */
|
PyStructSequence_SET_ITEM(result, 7, PyInt_FromLong(ru.ru_majflt));
|
||||||
ru.ru_nswap, /* number of swap outs */
|
PyStructSequence_SET_ITEM(result, 8, PyInt_FromLong(ru.ru_nswap));
|
||||||
ru.ru_inblock, /* block input operations */
|
PyStructSequence_SET_ITEM(result, 9, PyInt_FromLong(ru.ru_inblock));
|
||||||
ru.ru_oublock, /* block output operations */
|
PyStructSequence_SET_ITEM(result, 10, PyInt_FromLong(ru.ru_oublock));
|
||||||
ru.ru_msgsnd, /* messages sent */
|
PyStructSequence_SET_ITEM(result, 11, PyInt_FromLong(ru.ru_msgsnd));
|
||||||
ru.ru_msgrcv, /* messages received */
|
PyStructSequence_SET_ITEM(result, 12, PyInt_FromLong(ru.ru_msgrcv));
|
||||||
ru.ru_nsignals, /* signals received */
|
PyStructSequence_SET_ITEM(result, 13, PyInt_FromLong(ru.ru_nsignals));
|
||||||
ru.ru_nvcsw, /* voluntary context switches */
|
PyStructSequence_SET_ITEM(result, 14, PyInt_FromLong(ru.ru_nvcsw));
|
||||||
ru.ru_nivcsw /* involuntary context switches */
|
PyStructSequence_SET_ITEM(result, 15, PyInt_FromLong(ru.ru_nivcsw));
|
||||||
);
|
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
Py_DECREF(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,6 +216,9 @@ initresource(void)
|
||||||
}
|
}
|
||||||
Py_INCREF(ResourceError);
|
Py_INCREF(ResourceError);
|
||||||
PyModule_AddObject(m, "error", ResourceError);
|
PyModule_AddObject(m, "error", ResourceError);
|
||||||
|
PyStructSequence_InitType(&StructRUsageType, &struct_rusage_desc);
|
||||||
|
PyModule_AddObject(m, "struct_rusage",
|
||||||
|
(PyObject*) &StructRUsageType);
|
||||||
|
|
||||||
/* insert constants */
|
/* insert constants */
|
||||||
#ifdef RLIMIT_CPU
|
#ifdef RLIMIT_CPU
|
||||||
|
|
Loading…
Reference in New Issue