From 3efb6bf9e5acf3cf62df2854fd910c637a7209f9 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Fri, 28 Oct 2016 01:27:20 +0200 Subject: [PATCH] #799 / win: use oneshot() around num_threads() and num_ctx_switches(); speedup from 1.2x to 1.8x --- docs/index.rst | 8 ++++---- psutil/_pswindows.py | 28 +++++++++++++++++++--------- scripts/internal/bench_oneshot.py | 2 ++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index fb6b71163..f3caada6a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -823,11 +823,11 @@ Process class +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ | :meth:`status` | :meth:`nice` | :meth:`num_threads` | :meth:`name` | :meth:`memory_percent` | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ - | :meth:`terminal` | :meth:`num_handles` | | :meth:`memory_info` | :meth:`nice` | + | :meth:`terminal` | :meth:`num_ctx_switches` | | :meth:`memory_info` | :meth:`nice` | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ - | | | :meth:`create_time` | :meth:`memory_percent` | :meth:`num_threads` | + | | :meth:`num_handles` | :meth:`create_time` | :meth:`memory_percent` | :meth:`num_threads` | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ - | :meth:`gids` | | :meth:`gids` | :meth:`num_ctx_switches` | :meth:`ppid` | + | :meth:`gids` | :meth:`num_threads` | :meth:`gids` | :meth:`num_ctx_switches` | :meth:`ppid` | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ | :meth:`num_ctx_switches` | | :meth:`name` | :meth:`ppid` | :meth:`status` | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ @@ -843,7 +843,7 @@ Process class +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ | | | | | | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ - | *speedup: +2.5x* | | *speedup: +1.9x* | *speedup: +2.0x* | | + | *speedup: +2.5x* | *speedup: +1.8x* | *speedup: +1.9x* | *speedup: +2.0x* | | +------------------------------+------------------------------+------------------------------+------------------------------+--------------------------+ .. versionadded:: 5.0.0 diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index df34ee093..99df53a55 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -15,6 +15,7 @@ from . import _psutil_windows as cext from ._common import conn_tmap from ._common import isfile_strict +from ._common import memoize_when_activated from ._common import parse_environ_block from ._common import sockfam_to_enum from ._common import socktype_to_enum @@ -578,19 +579,24 @@ def __init__(self, pid): self._inctx = False self._handle = None + # --- oneshot() stuff + def oneshot_enter(self): self._inctx = True + self.oneshot_info.cache_activate() def oneshot_exit(self): self._inctx = False - if self._handle: - cext.win32_CloseHandle(self._handle) - self._handle = None + self.oneshot_info.cache_deactivate() + if self._handle is not None: + try: + cext.win32_CloseHandle(self._handle) + finally: + self._handle = None def get_handle(self): """Get a handle to this process. - If we're in oneshot() ctx manager tries to return the - cached handle. + If we're in oneshot() context returns the cached handle. """ if self._inctx: self._handle = self._handle or cext.win32_OpenProcess(self.pid) @@ -600,10 +606,11 @@ def get_handle(self): @contextlib.contextmanager def handle_ctx(self): - """Get a handle to this process. - If we're not in oneshot() ctx close the handle on exit - else tries to return the cached handle and avoid to close - the handle (will be close on oneshot() exit). + """Get a handle to this process as a context manager. + If we're not in a oneshot() context close the handle + when exiting the "with" statement, else try return the + cached handle (if available) and don't close it when + exiting the "with" statement. """ handle = self.get_handle() try: @@ -612,6 +619,7 @@ def handle_ctx(self): if not self._inctx: cext.win32_CloseHandle(handle) + @memoize_when_activated def oneshot_info(self): """Return multiple information about this process as a raw tuple. @@ -620,6 +628,8 @@ def oneshot_info(self): assert len(ret) == len(pinfo_map) return ret + # --- implementation + @wrap_exceptions def name(self): """Return process name, which on Windows is always the final diff --git a/scripts/internal/bench_oneshot.py b/scripts/internal/bench_oneshot.py index ad96ef5ae..5ab2266ef 100755 --- a/scripts/internal/bench_oneshot.py +++ b/scripts/internal/bench_oneshot.py @@ -95,7 +95,9 @@ 'ionice', 'memory_info', 'nice', + 'num_ctx_switches', 'num_handles', + 'num_threads', ] names = sorted(set(names))