Add -N option to powerd(8) to ignore "nice" time.

With powerd_flags="-N", this makes powerd(8) exclude "nice" time when
computing the CPU utilization.  This makes it possible to prevent
CPU-intensive "background" processes from spinning up the CPU.

Note that only *userland* CPU usage belonging to "nice" processes is
excluded; we do not track whether time spent in the kernel is on behalf
of nice or non-nice processes, so kernel-intensive nice processes can
still result in the CPU being sped up.

MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D23868
This commit is contained in:
Colin Percival 2020-02-29 22:31:23 +00:00
parent 9ea5bef27f
commit d91382866f
2 changed files with 26 additions and 10 deletions

View File

@ -37,6 +37,7 @@
.Op Fl i Ar percent
.Op Fl m Ar freq
.Op Fl M Ar freq
.Op Fl N
.Op Fl n Ar mode
.Op Fl p Ar ival
.Op Fl P Ar pidfile
@ -102,6 +103,10 @@ The default is 50% or lower.
Specifies the minimum frequency to throttle down to.
.It Fl M Ar freq
Specifies the maximum frequency to throttle up to.
.It Fl N
Treat "nice" time as idle for the purpose of load calculation;
i.e. do not increase the CPU frequency if the CPU is only busy
with "nice" processes.
.It Fl n Ar mode
Selects the
.Ar mode

View File

@ -86,7 +86,7 @@ static const char *modes[] = {
#define DEVDPIPE "/var/run/devd.pipe"
#define DEVCTL_MAXBUF 1024
static int read_usage_times(int *load);
static int read_usage_times(int *load, int nonice);
static int read_freqs(int *numfreqs, int **freqs, int **power,
int minfreq, int maxfreq);
static int set_freq(int freq);
@ -135,15 +135,17 @@ static struct timeval tried_devd;
* This function returns summary load of all CPUs. It was made so
* intentionally to not reduce performance in scenarios when several
* threads are processing requests as a pipeline -- running one at
* a time on different CPUs and waiting for each other.
* a time on different CPUs and waiting for each other. If nonice
* is nonzero, only user+sys+intr time will be counted as load; any
* nice time will be treated as if idle.
*/
static int
read_usage_times(int *load)
read_usage_times(int *load, int nonice)
{
static long *cp_times = NULL, *cp_times_old = NULL;
static int ncpus = 0;
size_t cp_times_len;
int error, cpu, i, total;
int error, cpu, i, total, excl;
if (cp_times == NULL) {
cp_times_len = 0;
@ -175,8 +177,12 @@ read_usage_times(int *load)
}
if (total == 0)
continue;
*load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] -
cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
excl = cp_times[cpu * CPUSTATES + CP_IDLE] -
cp_times_old[cpu * CPUSTATES + CP_IDLE];
if (nonice)
excl += cp_times[cpu * CPUSTATES + CP_NICE] -
cp_times_old[cpu * CPUSTATES + CP_NICE];
*load += 100 - excl * 100 / total;
}
}
@ -473,7 +479,7 @@ usage(void)
{
fprintf(stderr,
"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n");
"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-N] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n");
exit(1);
}
@ -490,6 +496,7 @@ main(int argc, char * argv[])
int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
uint64_t mjoules_used;
size_t len;
int nonice;
/* Default mode for all AC states is adaptive. */
mode_ac = mode_none = MODE_HIADAPTIVE;
@ -499,12 +506,13 @@ main(int argc, char * argv[])
poll_ival = DEFAULT_POLL_INTERVAL;
mjoules_used = 0;
vflag = 0;
nonice = 0;
/* User must be root to control frequencies. */
if (geteuid() != 0)
errx(1, "must be root to run");
while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:s:v")) != -1)
while ((ch = getopt(argc, argv, "a:b:i:m:M:Nn:p:P:r:s:v")) != -1)
switch (ch) {
case 'a':
parse_mode(optarg, &mode_ac, ch);
@ -539,6 +547,9 @@ main(int argc, char * argv[])
usage();
}
break;
case 'N':
nonice = 1;
break;
case 'n':
parse_mode(optarg, &mode_none, ch);
break;
@ -584,7 +595,7 @@ main(int argc, char * argv[])
err(1, "lookup freq_levels");
/* Check if we can read the load and supported freqs. */
if (read_usage_times(NULL))
if (read_usage_times(NULL, nonice))
err(1, "read_usage_times");
if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq))
err(1, "error reading supported CPU frequencies");
@ -766,7 +777,7 @@ main(int argc, char * argv[])
}
/* Adaptive mode; get the current CPU usage times. */
if (read_usage_times(&load)) {
if (read_usage_times(&load, nonice)) {
if (vflag)
warn("read_usage_times() failed");
continue;