Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
Re: getrusage() memory stats
To:
David Gwynne <david@gwynne.id.au>
Cc:
tech@openbsd.org
Date:
Fri, 06 Dec 2024 14:42:14 +0100

Download raw body.

Thread
> Date: Fri, 6 Dec 2024 16:13:59 +1000
> From: David Gwynne <david@gwynne.id.au>
> 
> this repurposes the memory usage fields in struct rusage to give the
> current memory usage info when using getrusage(RUSAGE_SELF). this
> is the same as what we can see in tools like top.
> 
> currently these fields are 0. they're documented as being max and some
> integral values i dont understand. having the current values is better
> than nothing.
> 
> im already using getrusage to collect metrics in some home grown
> software, having current memory usage nicely complements the cpu
> usage stats. some of these things run out of memory, so understanding
> the trend over time will be useful.
> 
> fwiw, netbsd also uses the current values to populate these fields, but
> didnt update their doco.
> 
> ok?

I don't think this is a good idea.  The getrusage(2) interface has
never been about capturing "current" values, but always about
"accumulated" values.

I guess maxrss is a bit of an odd one out here but the maximum is
still a value that is determined over the entire run.  I guess at
least here the "current" value can be seen as an approximation of the
true maximum.  But the maximum would be much more interesting as that
really is the relevant thing to measure to determine how much memory
you really need for your workload.  Is there a reason why you can't
use sysctl to measure the "current" values?

The 4.3BSD definition of struct rusage has spread widely to other
OSes.  Changing its interpretation just on OpenBSD isn't going to help
people trying to write portable code.

> Index: lib/libc/sys/getrusage.2
> ===================================================================
> RCS file: /cvs/src/lib/libc/sys/getrusage.2,v
> diff -u -p -r1.18 getrusage.2
> --- lib/libc/sys/getrusage.2	17 Jul 2024 13:29:05 -0000	1.18
> +++ lib/libc/sys/getrusage.2	6 Dec 2024 05:21:51 -0000
> @@ -64,10 +64,10 @@ the following structure:
>  struct rusage {
>          struct timeval ru_utime; /* user time used */
>          struct timeval ru_stime; /* system time used */
> -        long ru_maxrss;          /* max resident set size */
> -        long ru_ixrss;           /* integral shared text memory size */
> -        long ru_idrss;           /* integral unshared data size */
> -        long ru_isrss;           /* integral unshared stack size */
> +        long ru_maxrss;          /* resident set size */
> +        long ru_ixrss;           /* shared text memory size */
> +        long ru_idrss;           /* unshared data size */
> +        long ru_isrss;           /* unshared stack size */
>          long ru_minflt;          /* page reclaims */
>          long ru_majflt;          /* page faults */
>          long ru_nswap;           /* swaps */
> @@ -89,22 +89,18 @@ the total amount of time spent executing
>  the total amount of time spent in the system executing on behalf
>  of the process(es).
>  .It Fa ru_maxrss
> -the maximum resident set size utilized (in kilobytes).
> +the resident set size utilized (in kilobytes).
>  .It Fa ru_ixrss
> -an
> -.Dq integral
> -value indicating the amount of memory used
> +a value indicating the amount of memory used
>  by the text segment
>  that was also shared among other processes.
> -This value is expressed in units of kilobytes * ticks-of-execution.
> +This value is expressed in units of kilobytes.
>  .It Fa ru_idrss
> -an integral value of the amount of unshared memory residing in the
> -data segment of a process (expressed in units of
> -kilobytes * ticks-of-execution).
> +a value of the amount of unshared memory residing in the
> +data segment of a process (expressed in units of kilobytes).
>  .It Fa ru_isrss
> -an integral value of the amount of unshared memory residing in the
> -stack segment of a process (expressed in units of
> -kilobytes * ticks-of-execution).
> +a value of the amount of unshared memory residing in the
> +stack segment of a process (expressed in units of kilobytes).
>  .It Fa ru_minflt
>  the number of page faults serviced without any I/O activity; here
>  I/O activity is avoided by
> Index: sys/sys/resource.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/resource.h,v
> diff -u -p -r1.14 resource.h
> --- sys/sys/resource.h	25 Oct 2013 04:42:48 -0000	1.14
> +++ sys/sys/resource.h	6 Dec 2024 05:21:51 -0000
> @@ -58,11 +58,11 @@
>  struct	rusage {
>  	struct timeval ru_utime;	/* user time used */
>  	struct timeval ru_stime;	/* system time used */
> -	long	ru_maxrss;		/* max resident set size */
> +	long	ru_maxrss;		/* resident set size */
>  #define	ru_first	ru_ixrss
> -	long	ru_ixrss;		/* integral shared text memory size */
> -	long	ru_idrss;		/* integral unshared data " */
> -	long	ru_isrss;		/* integral unshared stack " */
> +	long	ru_ixrss;		/* shared text memory size */
> +	long	ru_idrss;		/* unshared data " */
> +	long	ru_isrss;		/* unshared stack " */
>  	long	ru_minflt;		/* page reclaims */
>  	long	ru_majflt;		/* page faults */
>  	long	ru_nswap;		/* swaps */
> Index: sys/kern/kern_resource.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_resource.c,v
> diff -u -p -r1.93 kern_resource.c
> --- sys/kern/kern_resource.c	10 Nov 2024 06:45:36 -0000	1.93
> +++ sys/kern/kern_resource.c	6 Dec 2024 05:21:51 -0000
> @@ -542,6 +542,18 @@ sys_getrusage(struct proc *p, void *v, r
>  	return (error);
>  }
>  
> +static void
> +ruspace(struct rusage *rup, struct proc *p)
> +{
> +	struct vmspace *vm = p->p_vmspace;
> +
> +	/* XXX these are all current values, not max or integrals */
> +	rup->ru_maxrss = vm_resident_count(vm) << (PAGE_SHIFT - 10);
> +	rup->ru_ixrss = vm->vm_tsize << (PAGE_SHIFT - 10);
> +	rup->ru_idrss = vm->vm_dused << (PAGE_SHIFT - 10); /* vm_dsize too? */
> +	rup->ru_isrss = vm->vm_ssize << (PAGE_SHIFT - 10);
> +}
> +
>  int
>  dogetrusage(struct proc *p, int who, struct rusage *rup)
>  {
> @@ -567,6 +579,7 @@ dogetrusage(struct proc *p, int who, str
>  		}
>  
>  		calcru(&tu, &rup->ru_utime, &rup->ru_stime, NULL);
> +		ruspace(rup, p);
>  		break;
>  
>  	case RUSAGE_THREAD:
> 
>