| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,7 +12,13 @@ | |||
| 12 | 12 | import sysconfig | |
| 13 | 13 | import tempfile | |
| 14 | 14 | import textwrap | |
| 15 | + import types | ||
| 15 | 16 | from collections.abc import Callable | |
| 17 | + _winapi: types.ModuleType | None | ||
| 18 | + try: | ||
| 19 | + import _winapi | ||
| 20 | + except ImportError: | ||
| 21 | + _winapi = None | ||
| 16 | 22 | ||
| 17 | 23 | from test import support | |
| 18 | 24 | from test.support import os_helper | |
@@ -754,10 +760,9 @@ def display_title(title): | |||
| 754 | 760 | print(flush=True) | |
| 755 | 761 | ||
| 756 | 762 | ||
| 757 | - def get_process_memory_usage(pid: int) -> int | None: | ||
| 758 | - """ | ||
| 759 | - Read the private memory in bytes from /proc/pid/smaps. | ||
| 760 | - """ | ||
| 763 | + def _get_process_memory_usage_linux(pid: int) -> int | None: | ||
| 764 | + # Linux implementation: read the private memory in bytes from | ||
| 765 | + # /proc/pid/smaps. | ||
| 761 | 766 | try: | |
| 762 | 767 | fp = open(f"/proc/{pid}/smaps", "rb") | |
| 763 | 768 | except OSError: | |
@@ -775,3 +780,26 @@ def get_process_memory_usage(pid: int) -> int | None: | |||
| 775 | 780 | return total | |
| 776 | 781 | except ProcessLookupError: | |
| 777 | 782 | return None | |
| 783 | + | ||
| 784 | + | ||
| 785 | + def _get_process_memory_usage_windows(pid: int) -> int | None: | ||
| 786 | + assert _winapi is not None # to make mypy happy | ||
| 787 | + handle = _winapi.OpenProcess(_winapi.PROCESS_QUERY_LIMITED_INFORMATION, | ||
| 788 | + False, pid) | ||
| 789 | + try: | ||
| 790 | + mem_info = _winapi.GetProcessMemoryInfo(handle) | ||
| 791 | + finally: | ||
| 792 | + _winapi.CloseHandle(handle) | ||
| 793 | + return mem_info['WorkingSetSize'] | ||
| 794 | + | ||
| 795 | + | ||
| 796 | + if _winapi is not None: | ||
| 797 | + get_process_memory_usage = _get_process_memory_usage_windows | ||
| 798 | + elif sys.platform == 'linux': | ||
| 799 | + get_process_memory_usage = _get_process_memory_usage_linux | ||
| 800 | + else: | ||
| 801 | + def get_process_memory_usage(pid: int) -> int | None: | ||
| 802 | + """ | ||
| 803 | + Get process memory usage in bytes. | ||
| 804 | + """ | ||
| 805 | + return None | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,13 @@ | |||
| 49 | 49 | #include <crtdbg.h> | |
| 50 | 50 | #include "winreparse.h" | |
| 51 | 51 | ||
| 52 | + // PSAPI_VERSION=2 redirects GetProcessMemoryInfo() to | ||
| 53 | + // K32GetProcessMemoryInfo() in kernel32.dll, so we don't need to link | ||
| 54 | + // psapi.lib. See: | ||
| 55 | + // https://learn.microsoft.com/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo | ||
| 56 | + #define PSAPI_VERSION 2 | ||
| 57 | + #include <psapi.h> // GetProcessMemoryInfo() | ||
| 58 | + | ||
| 52 | 59 | #if defined(MS_WIN32) && !defined(MS_WIN64) | |
| 53 | 60 | #define HANDLE_TO_PYNUM(handle) \ | |
| 54 | 61 | PyLong_FromUnsignedLong((unsigned long) handle) | |
@@ -3080,6 +3087,61 @@ _winapi_ReportEvent_impl(PyObject *module, HANDLE handle, | |||
| 3080 | 3087 | } | |
| 3081 | 3088 | ||
| 3082 | 3089 | ||
| 3090 | + /*[clinic input] | ||
| 3091 | + _winapi.GetProcessMemoryInfo | ||
| 3092 | + handle: HANDLE | ||
| 3093 | + / | ||
| 3094 | + | ||
| 3095 | + Return the memory usage of the given process handle as a dict. | ||
| 3096 | + [clinic start generated code]*/ | ||
| 3097 | + | ||
| 3098 | + static PyObject * | ||
| 3099 | + _winapi_GetProcessMemoryInfo_impl(PyObject *module, HANDLE handle) | ||
| 3100 | + /*[clinic end generated code: output=00a5d09732e84120 input=5b90ad61cdc68d2a]*/ | ||
| 3101 | + { | ||
| 3102 | + PROCESS_MEMORY_COUNTERS pmc; | ||
| 3103 | + if (!GetProcessMemoryInfo(handle, &pmc, sizeof(pmc))) { | ||
| 3104 | + return PyErr_SetFromWindowsErr(0); | ||
| 3105 | + } | ||
| 3106 | + | ||
| 3107 | + PyObject *result = PyDict_New(); | ||
| 3108 | + if (result == NULL) { | ||
| 3109 | + return NULL; | ||
| 3110 | + } | ||
| 3111 | + | ||
| 3112 | + #define ADD(ATTR) \ | ||
| 3113 | + do { \ | ||
| 3114 | + PyObject *obj = PyLong_FromSize_t(pmc.ATTR); \ | ||
| 3115 | + if (obj == NULL) { \ | ||
| 3116 | + goto error; \ | ||
| 3117 | + } \ | ||
| 3118 | + if (PyDict_SetItemString(result, #ATTR, obj) < 0) { \ | ||
| 3119 | + Py_DECREF(obj); \ | ||
| 3120 | + goto error; \ | ||
| 3121 | + } \ | ||
| 3122 | + Py_DECREF(obj); \ | ||
| 3123 | + } while (0) | ||
| 3124 | + | ||
| 3125 | + ADD(PageFaultCount); | ||
| 3126 | + ADD(PeakWorkingSetSize); | ||
| 3127 | + ADD(WorkingSetSize); | ||
| 3128 | + ADD(QuotaPeakPagedPoolUsage); | ||
| 3129 | + ADD(QuotaPagedPoolUsage); | ||
| 3130 | + ADD(QuotaPeakNonPagedPoolUsage); | ||
| 3131 | + ADD(QuotaNonPagedPoolUsage); | ||
| 3132 | + ADD(PagefileUsage); | ||
| 3133 | + ADD(PeakPagefileUsage); | ||
| 3134 | + | ||
| 3135 | + #undef ADD | ||
| 3136 | + | ||
| 3137 | + return result; | ||
| 3138 | + | ||
| 3139 | + error: | ||
| 3140 | + Py_DECREF(result); | ||
| 3141 | + return NULL; | ||
| 3142 | + } | ||
| 3143 | + | ||
| 3144 | + | ||
| 3083 | 3145 | static PyMethodDef winapi_functions[] = { | |
| 3084 | 3146 | _WINAPI_CLOSEHANDLE_METHODDEF | |
| 3085 | 3147 | _WINAPI_CONNECTNAMEDPIPE_METHODDEF | |
@@ -3130,6 +3192,7 @@ static PyMethodDef winapi_functions[] = { | |||
| 3130 | 3192 | _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF | |
| 3131 | 3193 | _WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF | |
| 3132 | 3194 | _WINAPI_COPYFILE2_METHODDEF | |
| 3195 | + _WINAPI_GETPROCESSMEMORYINFO_METHODDEF | ||
| 3133 | 3196 | {NULL, NULL} | |
| 3134 | 3197 | }; | |
| 3135 | 3198 | ||
@@ -3226,6 +3289,7 @@ static int winapi_exec(PyObject *m) | |||
| 3226 | 3289 | WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); | |
| 3227 | 3290 | WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE); | |
| 3228 | 3291 | WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE); | |
| 3292 | + WINAPI_CONSTANT(F_DWORD, PROCESS_QUERY_LIMITED_INFORMATION); | ||
| 3229 | 3293 | WINAPI_CONSTANT(F_DWORD, SEC_COMMIT); | |
| 3230 | 3294 | WINAPI_CONSTANT(F_DWORD, SEC_IMAGE); | |
| 3231 | 3295 | WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments