From 3343281309ec3c2d91a09b2b6e23bec117e21271 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 15:45:33 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20optimize=20psutil=20process?= =?UTF-8?q?=20scanning=20overhead?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: agno7766 <125467265+agno7766@users.noreply.github.com> --- .jules/bolt.md | 3 +++ desktop_services/excel_service.py | 18 ++++++++++++++---- desktop_services/operations_cockpit_service.py | 17 +++++++++++++---- 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..c566df5 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2025-05-20 - Optimize psutil.process_iter overhead +**Learning:** Querying all attributes (like `memory_info` and `status`) in `psutil.process_iter` for every process on the system is highly inefficient, as it fetches expensive data for many processes we don't care about. +**Action:** Only query `['pid', 'name']` initially. Lazily fetch expensive attributes like `memory_info()` and `status()` on the individual process objects only after filtering for our target processes (e.g., 'excel.exe'). Wrap these in try-except to safely catch process termination exceptions like `psutil.NoSuchProcess`, `psutil.AccessDenied`, and `psutil.ZombieProcess`. diff --git a/desktop_services/excel_service.py b/desktop_services/excel_service.py index d79b36b..16c5e63 100644 --- a/desktop_services/excel_service.py +++ b/desktop_services/excel_service.py @@ -206,17 +206,27 @@ def get_running_instances(self) -> List[Dict[str, Any]]: def _get_excel_process_snapshots(self) -> Dict[int, Dict[str, Any]]: """Find Excel processes with one psutil scan for refresh performance.""" snapshots: Dict[int, Dict[str, Any]] = {} - for proc in psutil.process_iter(["pid", "name", "memory_info", "status"]): + for proc in psutil.process_iter(["pid", "name"]): try: info = proc.info process_name = info.get("name") or "" - if process_name.lower() != "excel.exe": + if process_name.casefold() != "excel.exe": continue pid = int(info["pid"]) + + # Lazily fetch expensive attributes only for target processes to avoid + # querying them for all system processes during the psutil iteration. + try: + memory_info = proc.memory_info() + status = proc.status() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + memory_info = None + status = "running" + snapshots[pid] = { "name": process_name, - "memory_mb": self._memory_mb_from_info(info.get("memory_info")), - "status": info.get("status") or "running", + "memory_mb": self._memory_mb_from_info(memory_info), + "status": status or "running", } except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): continue diff --git a/desktop_services/operations_cockpit_service.py b/desktop_services/operations_cockpit_service.py index be2853d..f968732 100644 --- a/desktop_services/operations_cockpit_service.py +++ b/desktop_services/operations_cockpit_service.py @@ -852,19 +852,28 @@ def _default_processes() -> list[dict[str, Any]]: if psutil is None: return [] processes = [] - for proc in psutil.process_iter(["pid", "name", "memory_info", "status"]): + for proc in psutil.process_iter(["pid", "name"]): try: info = proc.info - except (psutil.NoSuchProcess, psutil.AccessDenied): + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): continue if str(info.get("name") or "").casefold() != "excel.exe": continue + + # Lazily fetch expensive attributes only for target processes to avoid + # querying them for all system processes during the psutil iteration. + try: + memory_info = proc.memory_info() + status = proc.status() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + memory_info = None + status = None processes.append( { "pid": info.get("pid"), "name": info.get("name"), - "memory_info": info.get("memory_info"), - "status": info.get("status"), + "memory_info": memory_info, + "status": status, } ) return processes