Re: [PATCH] free: Add 'available' memory if provided by the kernel

2018-10-30 Thread Denys Vlasenko
On Tue, Oct 30, 2018 at 2:46 PM Guillermo Rodriguez Garcia
 wrote:
>
> Thank you.
>
> One minor thing; in the code that has been commited, the seen_cached
> and seen_available vars have been combined into one
> (seen_cached_and_available). However the code now parses all lines in
> /proc/meminfo twice until both Cached and MemAvailable have been
> found:
>
>seen_cached_and_available = 2;
> while (fgets(buf, sizeof(buf), fp)) {
> if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1)
> if (--seen_cached_and_available == 0)
> break;
> if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1)
> if (--seen_cached_and_available == 0)
> break;
> }
>
> However the original code only checks for things it has not seen yet;
> for example if it finds "Cached" then it will only check for
> MemAvailable in the remaining lines:
>
>while (fgets(buf, sizeof(buf), f) != NULL && !(seen_cached &&
> seen_available)) {
>if (!seen_cached && sscanf(buf, "Cached: %lu %*s\n",
> cached_kb) == 1) {
>seen_cached = 1;
>}
>else if (!seen_available && sscanf(buf, "MemAvailable:
> %lu %*s\n", available_kb) == 1) {
>seen_available = 1;
>}
>}
>
> I think it would be convenient to revert this change and keep the two
> separate variables in order to avoid doing unnecessary work.


That's larger code. I don't think users of "free" are that
performance-sensitive.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] free: Add 'available' memory if provided by the kernel

2018-10-30 Thread Guillermo Rodriguez Garcia
Thank you.

One minor thing; in the code that has been commited, the seen_cached
and seen_available vars have been combined into one
(seen_cached_and_available). However the code now parses all lines in
/proc/meminfo twice until both Cached and MemAvailable have been
found:

   seen_cached_and_available = 2;
while (fgets(buf, sizeof(buf), fp)) {
if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1)
if (--seen_cached_and_available == 0)
break;
if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1)
if (--seen_cached_and_available == 0)
break;
}

However the original code only checks for things it has not seen yet;
for example if it finds "Cached" then it will only check for
MemAvailable in the remaining lines:

   while (fgets(buf, sizeof(buf), f) != NULL && !(seen_cached &&
seen_available)) {
   if (!seen_cached && sscanf(buf, "Cached: %lu %*s\n",
cached_kb) == 1) {
   seen_cached = 1;
   }
   else if (!seen_available && sscanf(buf, "MemAvailable:
%lu %*s\n", available_kb) == 1) {
   seen_available = 1;
   }
   }

I think it would be convenient to revert this change and keep the two
separate variables in order to avoid doing unnecessary work.

Best,

Guillermo

El mar., 30 oct. 2018 a las 14:15, Denys Vlasenko
() escribió:
>
> Applied, thanks
> On Thu, Oct 4, 2018 at 4:27 PM Guillermo Rodríguez
>  wrote:
> >
> > Show estimated available memory if this is provided by the
> > kernel. See [1] for the full story.
> >
> >  [1]: 
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
> >
> > Signed-off-by: Guillermo Rodriguez 
> > ---
> >  procps/free.c | 54 ++
> >  1 file changed, 34 insertions(+), 20 deletions(-)
> >
> > diff --git a/procps/free.c b/procps/free.c
> > index 0991713..e7ba974 100644
> > --- a/procps/free.c
> > +++ b/procps/free.c
> > @@ -44,27 +44,36 @@ static unsigned long long scale(unsigned long d)
> > return ((unsigned long long)d * G.mem_unit) >> G_unit_steps;
> >  }
> >
> > -static unsigned long parse_cached_kb(void)
> > +static unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long 
> > *available_kb)
> >  {
> > char buf[60]; /* actual lines we expect are ~30 chars or less */
> > FILE *f;
> > -   unsigned long cached = 0;
> > +   int seen_cached = 0;
> > +   int seen_available = 0;
> > +
> > +   *cached_kb = *available_kb = 0;
> >
> > f = xfopen_for_read("/proc/meminfo");
> > -   while (fgets(buf, sizeof(buf), f) != NULL) {
> > -   if (sscanf(buf, "Cached: %lu %*s\n", ) == 1)
> > -   break;
> > +   while (fgets(buf, sizeof(buf), f) != NULL && !(seen_cached && 
> > seen_available)) {
> > +   if (!seen_cached && sscanf(buf, "Cached: %lu %*s\n", 
> > cached_kb) == 1) {
> > +   seen_cached = 1;
> > +   }
> > +   else if (!seen_available && sscanf(buf, "MemAvailable: %lu 
> > %*s\n", available_kb) == 1) {
> > +   seen_available = 1;
> > +   }
> > }
> > fclose(f);
> >
> > -   return cached;
> > +   return seen_available;
> >  }
> >
> >  int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
> >  int free_main(int argc UNUSED_PARAM, char **argv 
> > IF_NOT_DESKTOP(UNUSED_PARAM))
> >  {
> > struct sysinfo info;
> > -   unsigned long long cached;
> > +   unsigned long long cached, available;
> > +   unsigned long cached_kb, available_kb;
> > +   int seen_available;
> >
> > INIT_G();
> >
> > @@ -95,17 +104,19 @@ int free_main(int argc UNUSED_PARAM, char **argv 
> > IF_NOT_DESKTOP(UNUSED_PARAM))
> > /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... 
> > */
> > G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
> >
> > -   /* Extract cached from /proc/meminfo and convert to mem_units */
> > -   cached = ((unsigned long long) parse_cached_kb() * 1024) / 
> > G.mem_unit;
> > +   /* Extract cached and memavailable from /proc/meminfo and convert 
> > to mem_units */
> > +   seen_available = parse_meminfo(_kb, _kb);
> > +   cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit;
> > +   available = ((unsigned long long) available_kb * 1024) / G.mem_unit;
> >
> > -   printf("   %11s%11s%11s%11s%11s%11s\n",
> > +   printf("   %12s%12s%12s%12s%12s%12s\n",
> > "total",
> > "used",
> > "free",
> > -   "shared", "buffers", "cached" /* swap and total don't have 
> > these columns */
> > +   "shared", "buff/cache", "available" /* swap and 

Re: [PATCH] free: Add 'available' memory if provided by the kernel

2018-10-30 Thread Denys Vlasenko
Applied, thanks
On Thu, Oct 4, 2018 at 4:27 PM Guillermo Rodríguez
 wrote:
>
> Show estimated available memory if this is provided by the
> kernel. See [1] for the full story.
>
>  [1]: 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
>
> Signed-off-by: Guillermo Rodriguez 
> ---
>  procps/free.c | 54 ++
>  1 file changed, 34 insertions(+), 20 deletions(-)
>
> diff --git a/procps/free.c b/procps/free.c
> index 0991713..e7ba974 100644
> --- a/procps/free.c
> +++ b/procps/free.c
> @@ -44,27 +44,36 @@ static unsigned long long scale(unsigned long d)
> return ((unsigned long long)d * G.mem_unit) >> G_unit_steps;
>  }
>
> -static unsigned long parse_cached_kb(void)
> +static unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long 
> *available_kb)
>  {
> char buf[60]; /* actual lines we expect are ~30 chars or less */
> FILE *f;
> -   unsigned long cached = 0;
> +   int seen_cached = 0;
> +   int seen_available = 0;
> +
> +   *cached_kb = *available_kb = 0;
>
> f = xfopen_for_read("/proc/meminfo");
> -   while (fgets(buf, sizeof(buf), f) != NULL) {
> -   if (sscanf(buf, "Cached: %lu %*s\n", ) == 1)
> -   break;
> +   while (fgets(buf, sizeof(buf), f) != NULL && !(seen_cached && 
> seen_available)) {
> +   if (!seen_cached && sscanf(buf, "Cached: %lu %*s\n", 
> cached_kb) == 1) {
> +   seen_cached = 1;
> +   }
> +   else if (!seen_available && sscanf(buf, "MemAvailable: %lu 
> %*s\n", available_kb) == 1) {
> +   seen_available = 1;
> +   }
> }
> fclose(f);
>
> -   return cached;
> +   return seen_available;
>  }
>
>  int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
>  int free_main(int argc UNUSED_PARAM, char **argv 
> IF_NOT_DESKTOP(UNUSED_PARAM))
>  {
> struct sysinfo info;
> -   unsigned long long cached;
> +   unsigned long long cached, available;
> +   unsigned long cached_kb, available_kb;
> +   int seen_available;
>
> INIT_G();
>
> @@ -95,17 +104,19 @@ int free_main(int argc UNUSED_PARAM, char **argv 
> IF_NOT_DESKTOP(UNUSED_PARAM))
> /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
> G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
>
> -   /* Extract cached from /proc/meminfo and convert to mem_units */
> -   cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit;
> +   /* Extract cached and memavailable from /proc/meminfo and convert to 
> mem_units */
> +   seen_available = parse_meminfo(_kb, _kb);
> +   cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit;
> +   available = ((unsigned long long) available_kb * 1024) / G.mem_unit;
>
> -   printf("   %11s%11s%11s%11s%11s%11s\n",
> +   printf("   %12s%12s%12s%12s%12s%12s\n",
> "total",
> "used",
> "free",
> -   "shared", "buffers", "cached" /* swap and total don't have 
> these columns */
> +   "shared", "buff/cache", "available" /* swap and total don't 
> have these columns */
> );
>
> -#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n"
> +#define FIELDS_6 "%12llu%12llu%12llu%12llu%12llu%12llu\n"
>  #define FIELDS_3 (FIELDS_6 + 3*6)
>  #define FIELDS_2 (FIELDS_6 + 4*6)
>
> @@ -115,16 +126,19 @@ int free_main(int argc UNUSED_PARAM, char **argv 
> IF_NOT_DESKTOP(UNUSED_PARAM))
> scale(info.totalram - info.freeram),
> scale(info.freeram),
> scale(info.sharedram),
> -   scale(info.bufferram),
> -   scale(cached)
> +   scale(info.bufferram) + scale(cached),
> +   scale(available)
> );
> -   /* Show alternate, more meaningful busy/free numbers by counting
> +   /* On kernels < 3.14, MemAvailable is not provided.
> +* Show alternate, more meaningful busy/free numbers by counting
>  * buffer cache as free memory. */
> -   printf("-/+ buffers/cache:");
> -   printf(FIELDS_2,
> -   scale(info.totalram - info.freeram - info.bufferram - cached),
> -   scale(info.freeram + info.bufferram + cached)
> -   );
> +   if (!seen_available) {
> +   printf("-/+ buffers/cache:");
> +   printf(FIELDS_2,
> +   scale(info.totalram - info.freeram - info.bufferram - 
> cached),
> +   scale(info.freeram + info.bufferram + cached)
> +   );
> +   }
>  #if BB_MMU
> printf("Swap:  ");
> printf(FIELDS_3,
> --
> 1.9.1
>
> ___
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox