|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 06/24] xen: credit2: implement yield()
On 20/09/16 14:25, George Dunlap wrote:
> On 17/08/16 18:18, Dario Faggioli wrote:
>> When a vcpu explicitly yields it is usually giving
>> us an advice of "let someone else run and come back
>> to me in a bit."
>>
>> Credit2 isn't, so far, doing anything when a vcpu
>> yields, which means an yield is basically a NOP (well,
>> actually, it's pure overhead, as it causes the scheduler
>> kick in, but the result is --at least 99% of the time--
>> that the very same vcpu that yielded continues to run).
>>
>> Implement a "preempt bias", to be applied to yielding
>> vcpus. Basically when evaluating what vcpu to run next,
>> if a vcpu that has just yielded is encountered, we give
>> it a credit penalty, and check whether there is anyone
>> else that would better take over the cpu (of course,
>> if there isn't the yielding vcpu will continue).
>>
>> The value of this bias can be configured with a boot
>> time parameter, and the default is set to 1 ms.
>>
>> Also, add an yield performance counter, and fix the
>> style of a couple of comments.
>>
>> Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx>
>> ---
>> Cc: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
>> Cc: Anshul Makkar <anshul.makkar@xxxxxxxxxx>
>> Cc: Jan Beulich <jbeulich@xxxxxxxx>
>> Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
>> ---
>> Note that this *only* consider the bias during the very scheduling decision
>> that retults from the vcpu calling yield. After that, the __CSFLAG_vcpu_yield
>> flag is reset, and during all furute scheduling decisions, the vcpu will
>> compete with the other ones with its own amount of credits.
>>
>> Alternatively, we can actually _subtract_ some credits to a yielding vcpu.
>> That will sort of make the effect of a call to yield last in time.
>>
>> I'm not sure which path is best. Personally, I like the subtract approach
>> (perhaps, with a smaller bias than 1ms), but I think the "one shot" behavior
>> implemented here is a good starting point. It is _something_, which is better
>> than nothing, which is what we have without this patch! :-) It's lightweight
>> (in its impact on the crediting algorithm, I mean), and benchmarks looks
>> nice,
>> so I propose we go for this one, and explore the "permanent" --subtraction
>> based-- solution a bit more.
>> ---
>> docs/misc/xen-command-line.markdown | 10 ++++++
>> xen/common/sched_credit2.c | 62
>> +++++++++++++++++++++++++++++++----
>> xen/common/schedule.c | 2 +
>> xen/include/xen/perfc_defn.h | 1 +
>> 4 files changed, 68 insertions(+), 7 deletions(-)
>>
>> diff --git a/docs/misc/xen-command-line.markdown
>> b/docs/misc/xen-command-line.markdown
>> index 3a250cb..5f469b1 100644
>> --- a/docs/misc/xen-command-line.markdown
>> +++ b/docs/misc/xen-command-line.markdown
>> @@ -1389,6 +1389,16 @@ Choose the default scheduler.
>> ### sched\_credit2\_migrate\_resist
>> > `= <integer>`
>>
>> +### sched\_credit2\_yield\_bias
>> +> `= <integer>`
>> +
>> +> Default: `1000`
>> +
>> +Set how much a yielding vcpu will be penalized, in order to actually
>> +give a chance to run to some other vcpu. This is basically a bias, in
>> +favour of the non-yielding vcpus, expressed in microseconds (default
>> +is 1ms).
>> +
>> ### sched\_credit\_tslice\_ms
>> > `= <integer>`
>>
>> diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
>> index a3d7beb..569174b 100644
>> --- a/xen/common/sched_credit2.c
>> +++ b/xen/common/sched_credit2.c
>> @@ -144,6 +144,9 @@
>> #define CSCHED2_MIGRATE_RESIST ((opt_migrate_resist)*MICROSECS(1))
>> /* How much to "compensate" a vcpu for L2 migration */
>> #define CSCHED2_MIGRATE_COMPENSATION MICROSECS(50)
>> +/* How big of a bias we should have against a yielding vcpu */
>> +#define CSCHED2_YIELD_BIAS ((opt_yield_bias)*MICROSECS(1))
>> +#define CSCHED2_YIELD_BIAS_MIN CSCHED2_MIN_TIMER
>> /* Reset: Value below which credit will be reset. */
>> #define CSCHED2_CREDIT_RESET 0
>> /* Max timer: Maximum time a guest can be run for. */
>> @@ -181,11 +184,20 @@
>> */
>> #define __CSFLAG_runq_migrate_request 3
>> #define CSFLAG_runq_migrate_request (1<<__CSFLAG_runq_migrate_request)
>> -
>> +/*
>> + * CSFLAG_vcpu_yield: this vcpu was running, and has called vcpu_yield().
>> The
>> + * scheduler is invoked to see if we can give the cpu to someone else, and
>> + * get back to the yielding vcpu in a while.
>> + */
>> +#define __CSFLAG_vcpu_yield 4
>> +#define CSFLAG_vcpu_yield (1<<__CSFLAG_vcpu_yield)
>>
>> static unsigned int __read_mostly opt_migrate_resist = 500;
>> integer_param("sched_credit2_migrate_resist", opt_migrate_resist);
>>
>> +static unsigned int __read_mostly opt_yield_bias = 1000;
>> +integer_param("sched_credit2_yield_bias", opt_yield_bias);
>> +
>> /*
>> * Useful macros
>> */
>> @@ -1432,6 +1444,14 @@ out:
>> }
>>
>> static void
>> +csched2_vcpu_yield(const struct scheduler *ops, struct vcpu *v)
>> +{
>> + struct csched2_vcpu * const svc = CSCHED2_VCPU(v);
>> +
>> + __set_bit(__CSFLAG_vcpu_yield, &svc->flags);
>> +}
>> +
>> +static void
>> csched2_context_saved(const struct scheduler *ops, struct vcpu *vc)
>> {
>> struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
>> @@ -2247,10 +2267,22 @@ runq_candidate(struct csched2_runqueue_data *rqd,
>> struct list_head *iter;
>> struct csched2_vcpu *snext = NULL;
>> struct csched2_private *prv = CSCHED2_PRIV(per_cpu(scheduler, cpu));
>> + int yield_bias = 0;
>>
>> /* Default to current if runnable, idle otherwise */
>> if ( vcpu_runnable(scurr->vcpu) )
>> + {
>> + /*
>> + * The way we actually take yields into account is like this:
>> + * if scurr is yielding, when comparing its credits with other
>> + * vcpus in the runqueue, act like those other vcpus had yield_bias
>> + * more credits.
>> + */
>> + if ( unlikely(scurr->flags & CSFLAG_vcpu_yield) )
>> + yield_bias = CSCHED2_YIELD_BIAS;
>> +
>> snext = scurr;
>> + }
>> else
>> snext = CSCHED2_VCPU(idle_vcpu[cpu]);
>>
>> @@ -2268,6 +2300,7 @@ runq_candidate(struct csched2_runqueue_data *rqd,
>> list_for_each( iter, &rqd->runq )
>> {
>> struct csched2_vcpu * svc = list_entry(iter, struct csched2_vcpu,
>> runq_elem);
>> + int svc_credit = svc->credit + yield_bias;
>>
>> /* Only consider vcpus that are allowed to run on this processor. */
>> if ( !cpumask_test_cpu(cpu, svc->vcpu->cpu_hard_affinity) )
>> @@ -2288,19 +2321,23 @@ runq_candidate(struct csched2_runqueue_data *rqd,
>> continue;
>> }
>>
>> - /* If this is on a different processor, don't pull it unless
>> - * its credit is at least CSCHED2_MIGRATE_RESIST higher. */
>> + /*
>> + * If this is on a different processor, don't pull it unless
>> + * its credit is at least CSCHED2_MIGRATE_RESIST higher.
>> + */
>> if ( svc->vcpu->processor != cpu
>> - && snext->credit + CSCHED2_MIGRATE_RESIST > svc->credit )
>> + && snext->credit + CSCHED2_MIGRATE_RESIST > svc_credit )
>> {
>> (*pos)++;
>> SCHED_STAT_CRANK(migrate_resisted);
>> continue;
>> }
>>
>> - /* If the next one on the list has more credit than current
>> - * (or idle, if current is not runnable), choose it. */
>> - if ( svc->credit > snext->credit )
>> + /*
>> + * If the next one on the list has more credit than current
>> + * (or idle, if current is not runnable), choose it.
>> + */
>> + if ( svc_credit > snext->credit )
>> snext = svc;
>
> Hmm, if we change snext, shouldn't we also zero out the yield bias?
> Otherwise vcpus competing with snext (which will at this point have had
> the YIELD flag cleared) will be given the yield bonus as well, which is
> not what we want. In fact, I think in this case we'll always choose the
> *last* vcpu on the list unless there's one where the gap between N and
> N+1 is greater than YIELD_BIAS, won't it?
Oops -- just noticed the next line:
/* In any case, if we got this far, break. */
break;
Nevermind. :-)
-George
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |