diff --git a/Doc/lib/libresource.tex b/Doc/lib/libresource.tex index 33de531947e..6ec975b6ff9 100644 --- a/Doc/lib/libresource.tex +++ b/Doc/lib/libresource.tex @@ -133,50 +133,56 @@ not be available from this module on that platform. \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} - 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 by the \var{who} parameter. The \var{who} parameter should be specified using one of the \constant{RUSAGE_*} constants described below. - The elements of the return value each - describe how a particular system resource has been used, e.g. amount - of time spent running is user mode or number of times the process was - swapped out of main memory. Some values are dependent on the clock - tick internal, e.g. the amount of memory the process is using. + The fields of the return value each describe how a particular system + resource has been used, e.g. amount of time spent running is user mode + or number of times the process was swapped out of main memory. Some + values are dependent on the clock tick internal, e.g. the amount of + memory the process is using. - The first two elements of the return value are floating point values - representing the amount of time spent executing in user mode and the - 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: + For backward compatibility, the return value is also accessible as + a tuple of 16 elements. -\begin{tableii}{r|l}{code}{Offset}{Resource} - \lineii{0}{time in user mode (float)} - \lineii{1}{time in system mode (float)} - \lineii{2}{maximum resident set size} - \lineii{3}{shared memory size} - \lineii{4}{unshared memory size} - \lineii{5}{unshared stack size} - \lineii{6}{page faults not requiring I/O} - \lineii{7}{page faults requiring I/O} - \lineii{8}{number of swap outs} - \lineii{9}{block input operations} - \lineii{10}{block output operations} - \lineii{11}{messages sent} - \lineii{12}{messages received} - \lineii{13}{signals received} - \lineii{14}{voluntary context switches} - \lineii{15}{involuntary context switches} -\end{tableii} + The fields \member{ru_utime} and \member{ru_stime} of the return value + are floating point values representing the amount of time spent + executing in user mode and the 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{tableiii}{r|l|l}{code}{Index}{Field}{Resource} + \lineiii{0}{\member{ru_utime}}{time in user mode (float)} + \lineiii{1}{\member{ru_stime}}{time in system mode (float)} + \lineiii{2}{\member{ru_maxrss}}{maximum resident set size} + \lineiii{3}{\member{ru_ixrss}}{shared memory size} + \lineiii{4}{\member{ru_idrss}}{unshared memory size} + \lineiii{5}{\member{ru_isrss}}{unshared stack size} + \lineiii{6}{\member{ru_minflt}}{page faults not requiring I/O} + \lineiii{7}{\member{ru_majflt}}{page faults requiring I/O} + \lineiii{8}{\member{ru_nswap}}{number of swap outs} + \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 \var{who} parameter is specified. It may also raise \exception{error} exception in unusual circumstances. + + \versionchanged[Added access to values as attributes of the + returned object]{2.3} \end{funcdesc} \begin{funcdesc}{getpagesize}{} diff --git a/Misc/ACKS b/Misc/ACKS index 4f5ea8d8a3c..1e69c7aae74 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -413,6 +413,7 @@ Joel Shprentz Itamar Shtull-Trauring Eric Siegerman Paul Sijben +Kirill Simonov Nathan Paul Simons Janne Sinkkonen George Sipe diff --git a/Misc/NEWS b/Misc/NEWS index bb5792cd662..cd61d0ee62e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,7 +56,8 @@ Extension modules hole was quickly plugged in zlib-1.1.4, and the Windows build of 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 'u' indicates Py_UNICODE arrays. For those, .tounicode and diff --git a/Modules/resource.c b/Modules/resource.c index ecd992ed2bb..4d8d4faa014 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -1,5 +1,6 @@ #include "Python.h" +#include "structseq.h" #include #include #include @@ -16,11 +17,48 @@ 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 * resource_getrusage(PyObject *self, PyObject *args) { int who; struct rusage ru; + PyObject *result; if (!PyArg_ParseTuple(args, "i:getrusage", &who)) return NULL; @@ -35,29 +73,35 @@ resource_getrusage(PyObject *self, PyObject *args) return NULL; } - /* Yeah, this 16-tuple is way ugly. It's probably a lot less - ugly than a dictionary with keys (or object attributes) - named things like 'ixrss'. - */ - return Py_BuildValue( - "ddiiiiiiiiiiiiii", - doubletime(ru.ru_utime), /* user time used */ - doubletime(ru.ru_stime), /* system time used */ - ru.ru_maxrss, /* max. resident set size */ - ru.ru_ixrss, /* shared memory size */ - ru.ru_idrss, /* unshared memory size */ - ru.ru_isrss, /* unshared stack size */ - ru.ru_minflt, /* page faults not requiring I/O*/ - ru.ru_majflt, /* page faults requiring I/O */ - ru.ru_nswap, /* number of swap outs */ - ru.ru_inblock, /* block input operations */ - ru.ru_oublock, /* block output operations */ - ru.ru_msgsnd, /* messages sent */ - ru.ru_msgrcv, /* messages received */ - ru.ru_nsignals, /* signals received */ - ru.ru_nvcsw, /* voluntary context switches */ - ru.ru_nivcsw /* involuntary context switches */ - ); + result = PyStructSequence_New(&StructRUsageType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru.ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru.ru_stime))); + PyStructSequence_SET_ITEM(result, 2, PyInt_FromLong(ru.ru_maxrss)); + PyStructSequence_SET_ITEM(result, 3, PyInt_FromLong(ru.ru_ixrss)); + PyStructSequence_SET_ITEM(result, 4, PyInt_FromLong(ru.ru_idrss)); + PyStructSequence_SET_ITEM(result, 5, PyInt_FromLong(ru.ru_isrss)); + PyStructSequence_SET_ITEM(result, 6, PyInt_FromLong(ru.ru_minflt)); + PyStructSequence_SET_ITEM(result, 7, PyInt_FromLong(ru.ru_majflt)); + PyStructSequence_SET_ITEM(result, 8, PyInt_FromLong(ru.ru_nswap)); + PyStructSequence_SET_ITEM(result, 9, PyInt_FromLong(ru.ru_inblock)); + PyStructSequence_SET_ITEM(result, 10, PyInt_FromLong(ru.ru_oublock)); + PyStructSequence_SET_ITEM(result, 11, PyInt_FromLong(ru.ru_msgsnd)); + PyStructSequence_SET_ITEM(result, 12, PyInt_FromLong(ru.ru_msgrcv)); + PyStructSequence_SET_ITEM(result, 13, PyInt_FromLong(ru.ru_nsignals)); + PyStructSequence_SET_ITEM(result, 14, PyInt_FromLong(ru.ru_nvcsw)); + 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); PyModule_AddObject(m, "error", ResourceError); + PyStructSequence_InitType(&StructRUsageType, &struct_rusage_desc); + PyModule_AddObject(m, "struct_rusage", + (PyObject*) &StructRUsageType); /* insert constants */ #ifdef RLIMIT_CPU