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
> 

Reply via email to