actually, i thought about that as well - implementing that will require some major refactorings in the codebase. will have a look at it when i get at it. appreciate any input and/or patches/commits.
cheers On Sat, Jul 26, 2025 at 01:07:11PM +0200, Hiltjo Posthuma wrote: > I don't use slstatus, but wouldn't it be more logical to read meminfo once and > store the used variables? Then use them for each status indicator. > > Now for each variable it reads and parses all the lines from /proc/meminfo > each > time. > > Just an idea, > > On Thu, Jul 24, 2025 at 10:51:59PM +0200, g...@suckless.org wrote: > > commit 8723e8b8c69c08bae8abe02ea1f4a49758b8bdfc > > Author: drkhsh <m...@drkhsh.at> > > AuthorDate: Thu Jul 24 22:41:25 2025 +0200 > > Commit: drkhsh <m...@drkhsh.at> > > CommitDate: Thu Jul 24 22:41:25 2025 +0200 > > > > more concise memory calculation on Linux > > > > more flexible parsing for /proc/meminfo to take shared and reclaimable > > memory into account. this matches the output with free(1). > > > > additionally this could fix some corner cases, as the order of fields in > > /proc/meminfo is not strictly defined. > > > > slstatus: > > percent 81% free 2.5 Gi total 23.4 Gi used 19.0 Gi > > > > free(1): > > total used free shared buff/cache > > available > > Mem: 23Gi 19Gi 2.5Gi 1.3Gi 3.2Gi > > 3.6Gi > > > > diff --git a/components/ram.c b/components/ram.c > > index 15c4b74..bf71dcf 100644 > > --- a/components/ram.c > > +++ b/components/ram.c > > @@ -11,36 +11,45 @@ > > ram_free(const char *unused) > > { > > uintmax_t free; > > + FILE *fp; > > > > - if (pscanf("/proc/meminfo", > > - "MemTotal: %ju kB\n" > > - "MemFree: %ju kB\n" > > - "MemAvailable: %ju kB\n", > > - &free, &free, &free) != 3) > > + if (!(fp = fopen("/proc/meminfo", "r"))) > > return NULL; > > > > + if (lscanf(fp, "MemFree:", "%ju kB", &free) != 1) { > > + fclose(fp); > > + return NULL; > > + } > > + > > + fclose(fp); > > return fmt_human(free * 1024, 1024); > > } > > > > const char * > > ram_perc(const char *unused) > > { > > - uintmax_t total, free, buffers, cached; > > + uintmax_t total, free, buffers, cached, shmem, sreclaimable; > > int percent; > > + FILE *fp; > > + > > + if (!(fp = fopen("/proc/meminfo", "r"))) > > + return NULL; > > > > - if (pscanf("/proc/meminfo", > > - "MemTotal: %ju kB\n" > > - "MemFree: %ju kB\n" > > - "MemAvailable: %ju kB\n" > > - "Buffers: %ju kB\n" > > - "Cached: %ju kB\n", > > - &total, &free, &buffers, &buffers, &cached) != 5) > > + if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 || > > + lscanf(fp, "MemFree:", "%ju kB", &free) != 1 || > > + lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 || > > + lscanf(fp, "Cached:", "%ju kB", &cached) != 1 || > > + lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 || > > + lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) { > > + fclose(fp); > > return NULL; > > + } > > + fclose(fp); > > > > if (total == 0) > > return NULL; > > > > - percent = 100 * ((total - free) - (buffers + cached)) / total; > > + percent = 100 * (total - free - buffers - cached - sreclaimable > > + shmem) / total; > > return bprintf("%d", percent); > > } > > > > @@ -59,18 +68,24 @@ > > const char * > > ram_used(const char *unused) > > { > > - uintmax_t total, free, buffers, cached, used; > > + uintmax_t total, free, buffers, cached, used, shmem, > > sreclaimable; > > + FILE *fp; > > + > > + if (!(fp = fopen("/proc/meminfo", "r"))) > > + return NULL; > > > > - if (pscanf("/proc/meminfo", > > - "MemTotal: %ju kB\n" > > - "MemFree: %ju kB\n" > > - "MemAvailable: %ju kB\n" > > - "Buffers: %ju kB\n" > > - "Cached: %ju kB\n", > > - &total, &free, &buffers, &buffers, &cached) != 5) > > + if (lscanf(fp, "MemTotal:", "%ju kB", &total) != 1 || > > + lscanf(fp, "MemFree:", "%ju kB", &free) != 1 || > > + lscanf(fp, "Buffers:", "%ju kB", &buffers) != 1 || > > + lscanf(fp, "Cached:", "%ju kB", &cached) != 1 || > > + lscanf(fp, "Shmem:", "%ju kB", &shmem) != 1 || > > + lscanf(fp, "SReclaimable:", "%ju kB", &sreclaimable) != 1) { > > + fclose(fp); > > return NULL; > > + } > > + fclose(fp); > > > > - used = (total - free - buffers - cached); > > + used = total - free - buffers - cached - sreclaimable + shmem; > > return fmt_human(used * 1024, 1024); > > } > > #elif defined(__OpenBSD__) > > diff --git a/util.c b/util.c > > index bca9b2e..d33cf9d 100644 > > --- a/util.c > > +++ b/util.c > > @@ -139,3 +139,20 @@ pscanf(const char *path, const char *fmt, ...) > > > > return (n == EOF) ? -1 : n; > > } > > + > > +int > > +lscanf(FILE *fp, const char *key, const char *fmt, void *res) > > +{ > > + int n; > > + char line[256]; > > + > > + n = -1; > > + while (fgets(line, sizeof(line), fp)) > > + if (strncmp(line, key, strlen(key)) == 0) { > > + n = sscanf(line + strlen(key), fmt, res); > > + break; > > + } > > + > > + rewind(fp); > > + return (n == 1) ? 1 : -1; > > +} > > diff --git a/util.h b/util.h > > index cf4b027..7a960aa 100644 > > --- a/util.h > > +++ b/util.h > > @@ -1,5 +1,6 @@ > > /* See LICENSE file for copyright and license details. */ > > #include <stdint.h> > > +#include <stdio.h> > > > > extern char buf[1024]; > > > > @@ -14,3 +15,4 @@ int esnprintf(char *str, size_t size, const char *fmt, > > ...); > > const char *bprintf(const char *fmt, ...); > > const char *fmt_human(uintmax_t num, int base); > > int pscanf(const char *path, const char *fmt, ...); > > +int lscanf(FILE *fp, const char *key, const char *fmt, void *res); > > > > -- > Kind regards, > Hiltjo >