Index: sys/kern/kern_runq.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_runq.c,v
retrieving revision 1.45
diff -p -u -r1.45 kern_runq.c
--- sys/kern/kern_runq.c        7 Jul 2016 06:55:43 -0000       1.45
+++ sys/kern/kern_runq.c        27 Nov 2016 07:54:03 -0000
@@ -80,7 +80,7 @@ typedef struct {
       uint32_t        r_bitmap[PRI_COUNT >> BITMAP_SHIFT];
       /* Counters */
       u_int           r_count;        /* Count of the threads */
-       u_int           r_avgcount;     /* Average count of threads */
+       u_int           r_avgcount;     /* Average count of threads (* 256) */
       u_int           r_mcount;       /* Count of migratable threads */
       /* Runqueues */
       queue_t         r_rt_queue[PRI_RT_COUNT];
@@ -118,6 +118,7 @@ int         sched_kpreempt_pri = 1000;
static u_int   cacheht_time;           /* Cache hotness time */
static u_int   min_catch;              /* Minimal LWP count for catching */
static u_int   balance_period;         /* Balance period */
+static u_int   average_weight;         /* Weight old thread count average */
static struct cpu_info *worker_ci;     /* Victim CPU */
#ifdef MULTIPROCESSOR
static struct callout balance_ch;      /* Callout of balancer */
@@ -138,6 +139,8 @@ runq_init(void)

       /* Minimal count of LWPs for catching */
       min_catch = 1;
+       /* Weight of historical average */
+       average_weight = 50;                    /*   0.5   */

       /* Initialize balancing callout and run it */
#ifdef MULTIPROCESSOR
@@ -525,6 +528,10 @@ sched_balance(void *nocallout)
       runqueue_t *ci_rq;
       CPU_INFO_ITERATOR cii;
       u_int highest;
+       u_int weight;
+
+       /* sanitize sysctl value */
+       weight = MIN(average_weight, 100);

       hci = curcpu();
       highest = 0;
@@ -533,8 +540,15 @@ sched_balance(void *nocallout)
       for (CPU_INFO_FOREACH(cii, ci)) {
               ci_rq = ci->ci_schedstate.spc_sched_info;

-               /* Average count of the threads */
-               ci_rq->r_avgcount = (ci_rq->r_avgcount + ci_rq->r_mcount) >> 1;
+               /*
+                * Average count of the threads
+                *
+                * The average is computed as a fixpoint number with
+                * 8 fractional bits.
+                */
+               ci_rq->r_avgcount = (
+                       weight * ci_rq->r_avgcount + (100 - weight) * 256 * ci_rq->r_mcount
+                       ) / 100;

               /* Look for CPU with the highest average */
               if (ci_rq->r_avgcount > highest) {
@@ -840,6 +854,12 @@ SYSCTL_SETUP(sysctl_sched_setup, "sysctl
               CTL_CREATE, CTL_EOL);
       sysctl_createv(clog, 0, &node, NULL,
               CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+               CTLTYPE_INT, "average_weight",
+               SYSCTL_DESCR("Thread count averaging weight (in percent)"),
+               NULL, 0, &average_weight, 0,
+               CTL_CREATE, CTL_EOL);
+       sysctl_createv(clog, 0, &node, NULL,
+               CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
               CTLTYPE_INT, "min_catch",
               SYSCTL_DESCR("Minimal count of threads for catching"),
               NULL, 0, &min_catch, 0,