[PATCH] Cygwin: proc: Cache system process information
Takashi Yano
takashi.yano@nifty.ne.jp
Fri Sep 4 03:58:56 GMT 2026
If a process reads /proc/<pid>/stat for multiple PIDs, current code
every time calls NtQuerySystemInformation(SystemProcessInformation).
In addition, the buffer size is estimated by calling that function
with increasing buffer size. This takes 15 - 20 msec. This is looks
short time, however it is not negligible in some situation. If the
number of the process is 100, reading /proc/<pid>/stat takes 1.5 -
2.0 sec. Due to this behaviour, process pane of the btop is very
heavy.
With this patch, system process information is cached per process
for a short time (20 msec) to improve efficiency. Also, the buffer
size needed by NtQuerySystemInformation() is stored in static area,
so that the number of function call is reduced (~1/7). As a result,
the process pane of btop becomes significantly light (takes only
~15 msec for 100 processes).
Signef-off-by: Takashi Yano <takashi.yano@nift.ne.jp>
Reviewed-by:
---
winsup/cygwin/fhandler/process.cc | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc
index 537a4b370..97f3e0a2f 100644
--- a/winsup/cygwin/fhandler/process.cc
+++ b/winsup/cygwin/fhandler/process.cc
@@ -1524,14 +1524,30 @@ get_process_state (DWORD dwProcessId, DWORD *num_threads)
{
/* This isn't really heavy magic - just go through the processes' threads
one by one and return a value accordingly. Errors are silently ignored. */
+ const ULONGLONG cache_time = 20;
+ static NO_COPY muto cache_guard;
NTSTATUS status;
- PSYSTEM_PROCESS_INFORMATION p, sp;
- ULONG n = 0x4000;
+ static PSYSTEM_PROCESS_INFORMATION p = NULL;
+ static ULONGLONG t0 = 0;
+ PSYSTEM_PROCESS_INFORMATION sp;
+ static ULONG last_n = 0x4000;
+ ULONG n;
int state =' ';
+ cache_guard.init ("get_process_state")->acquire ();
+ n = last_n;
+
+ if (GetTickCount64 () - t0 < cache_time && p)
+ goto reuse_query;
+ else if (p)
+ {
+ free (p);
+ p = NULL;
+ }
+
p = (PSYSTEM_PROCESS_INFORMATION) malloc (n);
if (!p)
- return state;
+ goto out;
while (true)
{
status = NtQuerySystemInformation (SystemProcessInformation,
@@ -1550,6 +1566,9 @@ get_process_state (DWORD dwProcessId, DWORD *num_threads)
status, RtlNtStatusToDosError (status));
goto out;
}
+ last_n = n;
+ t0 = GetTickCount64 ();
+reuse_query:
state = 'Z';
sp = p;
for (;;)
@@ -1579,7 +1598,7 @@ get_process_state (DWORD dwProcessId, DWORD *num_threads)
sp = (PSYSTEM_PROCESS_INFORMATION) ((char *) sp + sp->NextEntryOffset);
}
out:
- free (p);
+ cache_guard.release ();
return state;
}
--
2.51.0
More information about the Cygwin-patches
mailing list