From 08144df5ea3954bb3a70f8d2e061a452b89631ef Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 15 Mar 2021 13:43:37 +0100 Subject: [PATCH] initctl: fix %CPU listing bug and use hash table for faster lookup Two major bugs: `if (!cg)` and missing `strdup(path)`. Also convert to use std hash table for lookup of previous cpu load value for a given cgroup path. The hash table is sized after the current num. rows on the screen -- resize currently not supported. The value given to hcreate() should be 25% greater than the estimated num of entries, but we take a wild guess just to make sure we don't run out of space at runtime. Signed-off-by: Joachim Wiberg --- src/initctl.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/initctl.c b/src/initctl.c index 493728aa..fb3f1d28 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -29,8 +29,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -784,6 +786,7 @@ static struct cg *append(char *path) { struct cg *cg; char fn[256]; + ENTRY item; snprintf(fn, sizeof(fn), "%s/cpuacct.usage", path); if (access(fn, F_OK)) { @@ -795,30 +798,26 @@ static struct cg *append(char *path) if (!cg) err(1, "failed allocating struct cg"); - cg->cg_path = path; - if (!list) - list = cg; - else { - struct cg *tmp = list; + cg->cg_path = strdup(path); + if (list) + cg->cg_next = list; + list = cg; - while (tmp->cg_next) - tmp = tmp->cg_next; - tmp->cg_next = cg; - } + item.key = cg->cg_path; + item.data = cg; + if (!hsearch(item, ENTER)) + err(1, "failed adding to hash table"); return cg; } static struct cg *find(char *path) { - struct cg *cg; + ENTRY *ep, item = { path, NULL }; - for (cg = list; cg; cg = cg->cg_next) { - if (strcmp(cg->cg_path, path)) - continue; - - return cg; - } + ep = hsearch(item, FIND); + if (ep) + return ep->data; return append(path); } @@ -831,7 +830,7 @@ static float cgroup_cpuload(char *path) FILE *fp; cg = find(path); - if (cg) + if (!cg) return 0.0; snprintf(fn, sizeof(fn), "%s/cpuacct.usage", cg->cg_path); @@ -850,7 +849,6 @@ static float cgroup_cpuload(char *path) cg->cg_load = (float)(diff / 1000000); cg->cg_load /= 10.0; } - cg->cg_prev = curr; } @@ -888,6 +886,9 @@ static int dump_cgroup(char *path, char *pfx, int top) int i, n; int num; + if (top >= screen_rows) + return 0; + if (-1 == lstat(path, &st)) return 1; @@ -932,7 +933,7 @@ static int dump_cgroup(char *path, char *pfx, int top) } printf("%s/ [cpu.shares: %d]\n", nm, cgroup_shares(buf)); - rc += dump_cgroup(buf, prefix, top); + rc += dump_cgroup(buf, prefix, top + i); free(namelist[i]); } @@ -952,13 +953,16 @@ static int dump_cgroup(char *path, char *pfx, int top) if (pid <= 0) continue; - /* skip kernel threads for now */ + /* skip kernel threads for now (no cmdline) */ pid_comm(pid, comm, sizeof(comm)); if (pid_cmdline(pid, buf, sizeof(buf))) printf("%s%s%s %s%d %s %s%s\n", top ? " " : "", pfx, ++i == num ? END : FORK, CDIM, pid, comm, buf, CRST); + top += i; + if (top >= screen_rows) + break; } return fclose(fp); @@ -994,6 +998,9 @@ static int show_cgtop(char *arg) arg = path; } + if (!hcreate(screen_rows + 25)) + err(1, "failed creating hash table"); + while (1) { fputs("\e[2J\e[1;1H", stdout); if (heading)