> Date: Wed, 30 Jun 2010 14:32:26 -0400 (EDT) > From: Ted Unangst <ted.unan...@gmail.com> > > I like this one better. Slow down the poll interval just a little so it's > not so hysterical, but also go straight to 100. If you need CPU, you need > CPU. It still backs down slowly, but that's just to prevent getting > caught in slow mode again. It also pays attention to per-core load, much > better on smp machines. I'm running this now and will probably continue > to do so for a while.
Before this goes in, I'd like to get a chance to test this on the sparc64 laptop that I have at home, to check that the agorithm works well on slower machines as well. > Index: init_main.c > =================================================================== > RCS file: /home/tedu/cvs/src/sys/kern/init_main.c,v > retrieving revision 1.168 > diff -u -r1.168 init_main.c > --- init_main.c 29 Jun 2010 20:25:57 -0000 1.168 > +++ init_main.c 30 Jun 2010 18:23:22 -0000 > @@ -172,6 +172,72 @@ > EMUL_ENABLED | EMUL_NATIVE, > }; > > +struct timeout setperf_to; > + > +void auto_setperf(void *v); > +void > +auto_setperf(void *v) > +{ > + static uint64_t *idleticks, *totalticks; > + > + int i, j; > + CPU_INFO_ITERATOR cii; > + struct cpu_info *ci; > + > + int speedup; > + uint64_t idle, total, allidle, alltotal; > + > + extern int perflevel; > + > + if (!cpu_setperf) > + return; > + if (!idleticks) > + if (!(idleticks = malloc(sizeof(*idleticks) * ncpus, > + M_DEVBUF, M_NOWAIT | M_ZERO))) > + return; > + if (!totalticks) > + if (!(totalticks = malloc(sizeof(*totalticks) * ncpus, > + M_DEVBUF, M_NOWAIT | M_ZERO))) { > + free(idleticks, M_DEVBUF); > + return; > + } > + alltotal = allidle = 0; > + j = 0; > + speedup = 0; > + CPU_INFO_FOREACH(cii, ci) { > + total = 0; > + for (i = 0; i < CPUSTATES; i++) { > + total += ci->ci_schedstate.spc_cp_time[i]; > + } > + total -= totalticks[j]; > + idle = ci->ci_schedstate.spc_cp_time[CP_IDLE] - idleticks[j]; > + if (idle < total / 2) > + speedup = 1; > + alltotal += total; > + allidle += idle; > + idleticks[j] += idle; > + totalticks[j] += total; > + > + j++; > + } > + if (allidle < alltotal * 3 / 4) > + speedup = 1; > + > + if (speedup && perflevel != 100) { > + perflevel = 100; > + printf("going up %d\n", perflevel); > + cpu_setperf(perflevel); > + } else if (!speedup) { > + perflevel -= 10; > + if (perflevel < 0) > + perflevel = 0; > + else > + printf("going down %d\n", perflevel); > + cpu_setperf(perflevel); > + } > + > + timeout_add_msec(&setperf_to, 200); > +} > > /* > * System startup; initialize the world, create process 0, mount root > @@ -545,6 +611,9 @@ > */ > start_init_exec = 1; > wakeup((void *)&start_init_exec); > + > + timeout_set(&setperf_to, auto_setperf, NULL); > + timeout_add_msec(&setperf_to, 200); > > /* > * proc0: nothing to do, back to sleep