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.

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

Reply via email to