Calculate a per-runqueue decaying load average.
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
diff -r c557f4c76911 -r ab53467fcc74 xen/common/sched_credit2.c
--- a/xen/common/sched_credit2.c Thu Dec 23 12:25:44 2010 +0000
+++ b/xen/common/sched_credit2.c Thu Dec 23 12:25:58 2010 +0000
@@ -175,6 +175,18 @@
#define RQD(_ops, _cpu) (&CSCHED_PRIV(_ops)->rqd[c2r(_ops, _cpu)])
/*
+ * Shifts for load average.
+ * - granularity: Reduce granularity of time by a factor of 1000, so we can
use 32-bit maths
+ * - window shift: Given granularity shift, make the window about 1 second
+ * - scale shift: Shift up load by this amount rather than using fractions;
128 corresponds
+ * to a load of 1.
+ */
+#define LOADAVG_GRANULARITY_SHIFT (10)
+int opt_load_window_shift=18;
+#define LOADAVG_WINDOW_SHIFT_MIN 4
+integer_param("credit2_load_window_shift", opt_load_window_shift);
+
+/*
* Per-runqueue data
*/
struct csched_runqueue_data {
@@ -190,6 +202,8 @@
cpumask_t idle, /* Currently idle */
tickled; /* Another cpu in the queue is already targeted for
this one */
int load; /* Instantaneous load: Length of queue + num
non-idle threads */
+ s_time_t load_last_update; /* Last time average was updated */
+ s_time_t avgload; /* Decaying queue load */
};
/*
@@ -204,6 +218,8 @@
int runq_map[NR_CPUS];
cpumask_t active_queues; /* Queues which may have active cpus */
struct csched_runqueue_data rqd[NR_CPUS];
+
+ int load_window_shift;
};
/*
@@ -273,13 +289,34 @@
update_load(const struct scheduler *ops,
struct csched_runqueue_data *rqd, int change, s_time_t now)
{
+ struct csched_private *prv = CSCHED_PRIV(ops);
+ s_time_t delta=-1;
+
+ now >>= LOADAVG_GRANULARITY_SHIFT;
+
+ if ( rqd->load_last_update + (1ULL<<prv->load_window_shift) < now )
+ {
+ rqd->avgload = rqd->load << (1ULL<prv->load_window_shift);
+ }
+ else
+ {
+ delta = now - rqd->load_last_update;
+
+ rqd->avgload =
+ ( ( delta * ( (unsigned long long)rqd->load <<
prv->load_window_shift ) )
+ + ( ((1ULL<<prv->load_window_shift) - delta) * rqd->avgload ) )
>> prv->load_window_shift;
+ }
+
rqd->load += change;
-
+ rqd->load_last_update = now;
{
struct {
- unsigned load:4;
+ unsigned load:4, avgload:28;
+ int delta;
} d;
d.load = rqd->load;
+ d.avgload = rqd->avgload;
+ d.delta = delta;
trace_var(TRC_CSCHED2_UPDATE_LOAD, 0,
sizeof(d),
(unsigned char *)&d);
@@ -1610,6 +1647,15 @@
" WARNING: This is experimental software in development.\n" \
" Use at your own risk.\n");
+ printk(" load_window_shift: %d\n", opt_load_window_shift);
+
+ if ( opt_load_window_shift < LOADAVG_WINDOW_SHIFT_MIN )
+ {
+ printk("%s: opt_load_window_shift %d below min %d, resetting\n",
+ __func__, opt_load_window_shift, LOADAVG_WINDOW_SHIFT_MIN);
+ opt_load_window_shift = LOADAVG_WINDOW_SHIFT_MIN;
+ }
+
/* Basically no CPU information is available at this point; just
* set up basic structures, and a callback when the CPU info is
* available. */
@@ -1631,6 +1677,8 @@
prv->rqd[i].id = -1;
}
+ prv->load_window_shift = opt_load_window_shift;
+
return 0;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|