-
Notifications
You must be signed in to change notification settings - Fork 0
β‘ Bolt: optimize psutil process scanning overhead #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
Comment on lines
+868
to
+870
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In Useful? React with πΒ / π. |
||
| 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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
proc.memory_info()/proc.status()raisesNoSuchProcessin_get_excel_process_snapshots, the code now falls back tomemory_info=Noneandstatus="running"and still records the PID. This creates phantom Excel instances if a process exits betweenprocess_iterand the lazy attribute reads, soget_running_instances()can report dead processes as live with 0 MB memory. In this exception path, the process should be skipped instead of added.Useful? React with πΒ / π.