> 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

Reply via email to