powerd - Add options to set poll_rate and sample_time, adjust idle algorithm
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 16 Jan 2015 23:44:41 +0000 (15:44 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 16 Jan 2015 23:44:41 +0000 (15:44 -0800)
* Add -r poll_rate and -T sample_time.  The user can adjust the values
  to e.g. make a workstation react more quickly to UI operations coming
  out of idle and to take longer to return to idle.

* Use a shorter averaging time (3 poll intervals) for ratcheting up the
  speed and a longer averaging time (adjustable by -T) for ratcheting down
  the speed.

* Enhance the manual page, describe default values and make suggestions.

usr.sbin/powerd/powerd.8
usr.sbin/powerd/powerd.c

index a966e6a..38fdff1 100644 (file)
@@ -12,6 +12,8 @@
 .Op Fl dt
 .Op Fl p Ar hysteresis
 .Op Fl u Ar trigger_up
+.Op Fl r Ar poll_time
+.Op Fl T Ar sample_time
 .Sh DESCRIPTION
 The
 .Nm
@@ -35,6 +37,7 @@ to not go to the background and prints some debug output to
 .It Fl p Ar hysteresis
 Percent of the upper limit to subtract as an hysteresis value to scale
 down to the min frequency.
+The default is 10 (meaning 10%).
 .It Fl t
 Turbo mode.
 Disables switching to turbo mode as maximum frequency completely.
@@ -42,6 +45,21 @@ Switching to turbo mode as maximum frequency is enabled by default,
 if the CPU supports it.
 .It Fl u Ar trigger_up
 Per CPU load limit in percent to force maximum frequency.
+The default is 25 (meaning an instantanious load of 0.25 on a
+single cpu).  The load is calculated over 3 polls.
+It is suggested that this value not be made lower than
+around 7.
+.It Fl r Ar poll_time
+Polling time in seconds.  Default is 1.0.
+Setting this value lower will poll for load changes faster.
+For example, a workstation might want to use 0.2 or 0.4.
+.Nm can become unstable if you make this value too small.
+.It Fl T Ar sample_time
+Total sample interval in seconds.  Default is 8.0.
+This effects how quickly powerd ratchets down the frequency
+and cpus on an idle machine.  Longer times will ratchet down
+more slowly.
+For example, a workstation might want to use a value of 30.0.
 .El
 .Sh DIAGNOSTICS
 The
index 3733d34..96b8b91 100644 (file)
@@ -63,8 +63,8 @@ int DomEnd;
 int NCpus;
 int CpuCount[256];     /* # of cpus in any given domain */
 int CpuToDom[256];     /* domain a particular cpu belongs to */
-int Hysteresis = 10;
-double TriggerUp = 0.25;/* load per cpu to force max freq */
+int Hysteresis = 10;   /* percentage */
+double TriggerUp = 0.25;/* single-cpu load to force max freq */
 double TriggerDown; /* load per cpu to force the min freq */
 
 static void sigintr(int signo);
@@ -73,12 +73,20 @@ int
 main(int ac, char **av)
 {
        double qavg;
-       double savg;
+       double uavg;    /* uavg - used for speeding up */
+       double davg;    /* davg - used for slowing down */
+       double srt;
+       double pollrate;
        int ch;
+       int ustate;
+       int dstate;
        int nstate;
        char buf[64];
 
-       while ((ch = getopt(ac, av, "dp:tu:")) != -1) {
+       srt = 8.0;      /* time for samples - 8 seconds */
+       pollrate = 1.0; /* polling rate in seconds */
+
+       while ((ch = getopt(ac, av, "dp:r:tu:T:")) != -1) {
                switch(ch) {
                case 'd':
                        DebugOpt = 1;
@@ -92,6 +100,12 @@ main(int ac, char **av)
                case 'u':
                        TriggerUp = (double)strtol(optarg, NULL, 10) / 100;
                        break;
+               case 'r':
+                       pollrate = strtod(optarg, NULL);
+                       break;
+               case 'T':
+                       srt = strtod(optarg, NULL);
+                       break;
                default:
                        usage();
                        /* NOT REACHED */
@@ -156,11 +170,10 @@ main(int ac, char **av)
                 * dom0 exists.
                 */
                getcputime();
-               savg = 0.0;
 
                setupdominfo();
                if (DomBeg >= DomEnd) {
-                       sleep(1);
+                       usleep((int)(pollrate * 1000000.0));
                        continue;
                }
 
@@ -174,6 +187,13 @@ main(int ac, char **av)
         */
        signal(SIGINT, sigintr);
        signal(SIGTERM, sigintr);
+       uavg = 0.0;
+       davg = 0.0;
+
+       srt = srt / pollrate;   /* convert to sample count */
+
+       if (DebugOpt)
+               printf("samples for downgrading: %5.2f\n", srt);
 
        /*
         * Monitoring loop
@@ -184,21 +204,32 @@ main(int ac, char **av)
         */
        for (;;) {
                qavg = getcputime();
-               savg = (savg * 7.0 + qavg) / 8.0;
-
-               nstate = savg / TriggerUp;
-               if (nstate < CpuLimit)
-                       nstate = savg / TriggerDown;
+               uavg = (uavg * 2.0 + qavg) / 3.0;       /* speeding up */
+               davg = (davg * srt + qavg) / (srt + 1); /* slowing down */
+               if (davg < uavg)
+                       davg = uavg;
+
+               ustate = uavg / TriggerUp;
+               if (ustate < CpuLimit)
+                       ustate = uavg / TriggerDown;
+               dstate = davg / TriggerUp;
+               if (dstate < CpuLimit)
+                       dstate = davg / TriggerDown;
+
+               nstate = (ustate > dstate) ? ustate : dstate;
                if (nstate > NCpus)
                        nstate = NCpus;
+
                if (DebugOpt) {
-                       printf("\rqavg=%5.2f savg=%5.2f %2d/%2d ncpus=%d\r",
-                               qavg, savg, CpuLimit, DomLimit, nstate);
+                       printf("\rqavg=%5.2f uavg=%5.2f davg=%5.2f "
+                              "%2d/%2d ncpus=%d\r",
+                               qavg, uavg, davg,
+                               CpuLimit, DomLimit, nstate);
                        fflush(stdout);
                }
                if (nstate != CpuLimit)
                        acpi_setcpufreq(nstate);
-               sleep(1);
+               usleep((int)(pollrate * 1000000.0));
        }
 }