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,
