diff options
author | Lucas De Marchi <lucas.demarchi@intel.com> | 2024-05-01 12:38:50 -0500 |
---|---|---|
committer | Lucas De Marchi <lucas.demarchi@intel.com> | 2024-05-03 06:07:39 -0700 |
commit | 48382cb8641a46db18cf91ff1cd33baf87a56983 (patch) | |
tree | 8502a4f7849a191ce95f281a8685ceb6848035b2 | |
parent | e1d202abb373e78b80e92814924316ee6b52b569 (diff) |
lib/igt_drm_clients: lazy stat process
Only try to get task data like pid and name when that is required.
Typically most of the processes in a system don't have a drm fd open.
So only open and use /proc/<pid>/stat when it's needed.
For the data below, system is running with just a single drm client:
Before:
Performance counter stats for './build/tools/gputop -d 0.1 -n 10':
507.19 msec task-clock # 0.334 CPUs utilized
29 context-switches # 57.178 /sec
4 cpu-migrations # 7.887 /sec
75 page-faults # 147.874 /sec
(...)
1.518253637 seconds time elapsed
0.007989000 seconds user
0.503351000 seconds sys
After:
Performance counter stats for './build/tools/gputop -d 0.1 -n 10':
384.01 msec task-clock # 0.275 CPUs utilized
17 context-switches # 44.270 /sec
1 cpu-migrations # 2.604 /sec
74 page-faults # 192.705 /sec
(...)
1.397640800 seconds time elapsed
0.008106000 seconds user
0.385048000 seconds sys
Looking only at the execution time of igt_drm_clients_scan() over 10
runs.
Before: 47138890 nsec
After: 33978388 nsec
So in both methods it shows a ~25% speedup. It is expected that in a
system with more clients this won't be as high.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Link: https://lore.kernel.org/r/20240501174001.121324-1-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
-rw-r--r-- | lib/igt_drm_clients.c | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c index 40d494441..ab0c2cec2 100644 --- a/lib/igt_drm_clients.c +++ b/lib/igt_drm_clients.c @@ -368,26 +368,33 @@ static size_t readat2buf(int at, const char *name, char *buf, const size_t sz) } } -static bool get_task_name(const char *buffer, char *out, unsigned long sz) +static void get_task_data(int pid_dir, unsigned int *pid, char *task, size_t tasksz) { - char *s = index(buffer, '('); - char *e = rindex(buffer, ')'); - unsigned int len; + char buf[4096]; + char *s, *e; + size_t len; + if (!readat2buf(pid_dir, "stat", buf, sizeof(buf))) + return; + + s = strchr(buf, '('); + e = strchr(s, ')'); if (!s || !e) - return false; - assert(e >= s); + return; len = e - ++s; - if(!len || (len + 1) >= sz) - return false; + if (!len) + return; - strncpy(out, s, len); - out[len] = 0; + if (len + 1 > tasksz) + len = tasksz - 1; - return true; + strncpy(task, s, len); + task[len] = 0; + *pid = atoi(buf); } + static bool is_drm_fd(int fd_dir, const char *name, unsigned int *minor) { struct stat stat; @@ -481,13 +488,11 @@ igt_drm_clients_scan(struct igt_drm_clients *clients, return clients; while ((proc_dent = readdir(proc_dir)) != NULL) { - unsigned int client_pid, minor = 0; + unsigned int client_pid = 0, minor = 0; int pid_dir = -1, fd_dir = -1; struct dirent *fdinfo_dent; char client_name[64] = { }; DIR *fdinfo_dir = NULL; - char buf[4096]; - size_t count; if (proc_dent->d_type != DT_DIR) continue; @@ -499,17 +504,6 @@ igt_drm_clients_scan(struct igt_drm_clients *clients, if (pid_dir < 0) continue; - count = readat2buf(pid_dir, "stat", buf, sizeof(buf)); - if (!count) - goto next; - - client_pid = atoi(buf); - if (!client_pid) - goto next; - - if (!get_task_name(buf, client_name, sizeof(client_name))) - goto next; - fd_dir = openat(pid_dir, "fd", O_DIRECTORY | O_RDONLY); if (fd_dir < 0) goto next; @@ -542,6 +536,12 @@ igt_drm_clients_scan(struct igt_drm_clients *clients, minor, info.id)) continue; /* Skip duplicate fds. */ + if (!client_pid) { + get_task_data(pid_dir, &client_pid, client_name, + sizeof(client_name)); + assert(client_pid > 0); + } + c = igt_drm_clients_find(clients, IGT_DRM_CLIENT_PROBE, minor, info.id); if (!c) |