mirror of
https://github.com/python/cpython.git
synced 2026-06-09 03:12:34 +00:00
gh-150114: Log the memory usage in regrtest on FreeBSD (#150280)
Add _testcapi.get_process_memory_usage(). On FreeBSD, _testcapi is now linked to libkvm.
This commit is contained in:
parent
46e8f7a9e7
commit
dfe7ef6292
4 changed files with 91 additions and 6 deletions
|
|
@ -19,6 +19,10 @@
|
|||
import _winapi
|
||||
except ImportError:
|
||||
_winapi = None
|
||||
try:
|
||||
from _testcapi import get_process_memory_usage as _get_process_memory_usage
|
||||
except ImportError:
|
||||
_get_process_memory_usage = None
|
||||
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
|
|
@ -793,13 +797,17 @@ def _get_process_memory_usage_windows(pid: int) -> int | None:
|
|||
return mem_info['WorkingSetSize']
|
||||
|
||||
|
||||
if _winapi is not None:
|
||||
if _get_process_memory_usage is not None:
|
||||
def get_process_memory_usage(pid: int) -> int | None:
|
||||
try:
|
||||
return _get_process_memory_usage(pid)
|
||||
except ProcessLookupError:
|
||||
return None
|
||||
elif _winapi is not None:
|
||||
get_process_memory_usage = _get_process_memory_usage_windows
|
||||
elif sys.platform == 'linux':
|
||||
get_process_memory_usage = _get_process_memory_usage_linux
|
||||
else:
|
||||
def get_process_memory_usage(pid: int) -> int | None:
|
||||
"""
|
||||
Get process memory usage in bytes.
|
||||
"""
|
||||
return None
|
||||
get_process_memory_usage.__doc__ = "Get process memory usage in bytes."
|
||||
|
|
|
|||
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
# include <fcntl.h> // O_RDONLY
|
||||
# include <kvm.h> // kvm_openfiles()
|
||||
# include <limits.h> // _POSIX2_LINE_MAX
|
||||
# include <sys/sysctl.h> // KERN_PROC_PID
|
||||
# include <sys/user.h> // kinfo_proc definition
|
||||
# include <unistd.h> // sysconf()
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
PyMemAllocatorEx alloc;
|
||||
|
|
@ -684,6 +693,57 @@ tracemalloc_track_race(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
// Return RSS only. Per-process swap usage isn't readily available
|
||||
static PyObject*
|
||||
get_process_memory_usage(PyObject *self, PyObject *args)
|
||||
{
|
||||
int pid;
|
||||
if (!PyArg_ParseTuple(args, "i", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size <= 0) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
// Using /dev/null for vmcore avoids needing dump file.
|
||||
// NULL for kernel file uses running kernel.
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
kvm_t *kd = kvm_openfiles(NULL, "/dev/null", NULL, O_RDONLY, errbuf);
|
||||
if (kd == NULL) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
// KERN_PROC_PID filters for the specific process ID.
|
||||
int n_procs;
|
||||
struct kinfo_proc *kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &n_procs);
|
||||
if (kp == NULL) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
if (n_procs <= 0) {
|
||||
// Process with PID not found
|
||||
errno = ESRCH;
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
assert(n_procs == 1);
|
||||
|
||||
// ki_rssize is in pages. Convert to bytes.
|
||||
size_t rss = (size_t)kp[0].ki_rssize * page_size;
|
||||
kvm_close(kd);
|
||||
|
||||
return PyLong_FromSize_t(rss);
|
||||
|
||||
error:
|
||||
kvm_close(kd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static PyMethodDef test_methods[] = {
|
||||
{"pymem_api_misuse", pymem_api_misuse, METH_NOARGS},
|
||||
{"pymem_buffer_overflow", pymem_buffer_overflow, METH_NOARGS},
|
||||
|
|
@ -698,6 +758,9 @@ static PyMethodDef test_methods[] = {
|
|||
{"test_pymem_setrawallocators", test_pymem_setrawallocators, METH_NOARGS},
|
||||
{"test_pyobject_new", test_pyobject_new, METH_NOARGS},
|
||||
{"test_pyobject_setallocators", test_pyobject_setallocators, METH_NOARGS},
|
||||
#ifdef __FreeBSD__
|
||||
{"get_process_memory_usage", get_process_memory_usage, METH_VARARGS},
|
||||
#endif
|
||||
|
||||
// Tracemalloc tests
|
||||
{"tracemalloc_track", tracemalloc_track, METH_VARARGS},
|
||||
|
|
|
|||
11
configure
generated
vendored
11
configure
generated
vendored
|
|
@ -34499,6 +34499,15 @@ fi
|
|||
printf "%s\n" "$py_cv_module__hashlib" >&6; }
|
||||
|
||||
|
||||
case $ac_sys_system in #(
|
||||
# On FreeBSD, _testcapi.get_process_memory_usage() calls kvm_openfiles()
|
||||
# and so needs libkvm.
|
||||
FreeBSD*) :
|
||||
LIBKVM="-lkvm"
|
||||
;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testcapi" >&5
|
||||
printf %s "checking for stdlib extension module _testcapi... " >&6; }
|
||||
|
|
@ -34525,7 +34534,7 @@ fi
|
|||
then :
|
||||
|
||||
|
||||
as_fn_append MODULE_BLOCK "MODULE__TESTCAPI_LDFLAGS=$LIBATOMIC$as_nl"
|
||||
as_fn_append MODULE_BLOCK "MODULE__TESTCAPI_LDFLAGS=$LIBATOMIC $LIBKVM$as_nl"
|
||||
|
||||
fi
|
||||
if test "$py_cv_module__testcapi" = yes; then
|
||||
|
|
|
|||
|
|
@ -8428,10 +8428,15 @@ PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes],
|
|||
[$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS])
|
||||
|
||||
dnl test modules
|
||||
AS_CASE([$ac_sys_system],
|
||||
# On FreeBSD, _testcapi.get_process_memory_usage() calls kvm_openfiles()
|
||||
# and so needs libkvm.
|
||||
[FreeBSD*], [LIBKVM="-lkvm"]
|
||||
)
|
||||
PY_STDLIB_MOD([_testcapi],
|
||||
[test "$TEST_MODULES" = yes],
|
||||
dnl Modules/_testcapi needs -latomic for 32bit AIX build
|
||||
[], [], [$LIBATOMIC])
|
||||
[], [], [$LIBATOMIC $LIBKVM])
|
||||
PY_STDLIB_MOD([_testclinic], [test "$TEST_MODULES" = yes])
|
||||
PY_STDLIB_MOD([_testclinic_limited], [test "$TEST_MODULES" = yes])
|
||||
PY_STDLIB_MOD([_testlimitedcapi], [test "$TEST_MODULES" = yes])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue