diff mbox

[6/6] xen: sched: optimize exclusive pinning case (Credit1 & 2)

Message ID 149821532649.5914.2989728748602173556.stgit@Solace (mailing list archive)
State New, archived
Headers show

Commit Message

Dario Faggioli June 23, 2017, 10:55 a.m. UTC
Exclusive pinning of vCPUs is used, sometimes, for
achieving the highest level of determinism, and the
least possible overhead, for the vCPUs in question.

Although static 1:1 pinning is not recommended, for
general use cases, optimizing the tickling code (of
Credit1 and Credit2) is easy and cheap enough, so go
for it.

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
---
Cc: George Dunlap <george.dunlap@citrix.com>
Cc: Anshul Makkar <anshulmakkar@gmail.com>
---
 xen/common/sched_credit.c    |   19 +++++++++++++++++++
 xen/common/sched_credit2.c   |   21 ++++++++++++++++++++-
 xen/include/xen/perfc_defn.h |    1 +
 3 files changed, 40 insertions(+), 1 deletion(-)

Comments

George Dunlap July 21, 2017, 5:19 p.m. UTC | #1
On 06/23/2017 11:55 AM, Dario Faggioli wrote:
> Exclusive pinning of vCPUs is used, sometimes, for
> achieving the highest level of determinism, and the
> least possible overhead, for the vCPUs in question.
> 
> Although static 1:1 pinning is not recommended, for
> general use cases, optimizing the tickling code (of
> Credit1 and Credit2) is easy and cheap enough, so go
> for it.
> 
> Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
> ---
> Cc: George Dunlap <george.dunlap@citrix.com>
> Cc: Anshul Makkar <anshulmakkar@gmail.com>
> ---
>  xen/common/sched_credit.c    |   19 +++++++++++++++++++
>  xen/common/sched_credit2.c   |   21 ++++++++++++++++++++-
>  xen/include/xen/perfc_defn.h |    1 +
>  3 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
> index 4f6330e..85e014d 100644
> --- a/xen/common/sched_credit.c
> +++ b/xen/common/sched_credit.c
> @@ -429,6 +429,24 @@ static inline void __runq_tickle(struct csched_vcpu *new)
>      idlers_empty = cpumask_empty(&idle_mask);
>  
>      /*
> +     * Exclusive pinning is when a vcpu has hard-affinity with only one
> +     * cpu, and there is no other vcpu that has hard-affinity with that
> +     * same cpu. This is infrequent, but if it happens, is for achieving
> +     * the most possible determinism, and least possible overhead for
> +     * the vcpus in question.
> +     *
> +     * Try to identify the vast majority of these situations, and deal
> +     * with them quickly.
> +     */
> +    if ( unlikely(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity) == cpu &&

Won't this check entail a full "loop" of the cpumask?  It's cheap enough
if nr_cpu_ids is small; but don't we support (theoretically) 4096
logical cpus?

It seems like having a vcpu flag that identifies a vcpu as being pinned
would be a more efficient way to do this.  That way we could run this
check once whenever the hard affinity changed, rather than every time we
want to think about where to run this vcpu.

What do you think?

 -George
Dario Faggioli July 21, 2017, 7:55 p.m. UTC | #2
On Fri, 2017-07-21 at 18:19 +0100, George Dunlap wrote:
> On 06/23/2017 11:55 AM, Dario Faggioli wrote:
> > diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
> > index 4f6330e..85e014d 100644
> > --- a/xen/common/sched_credit.c
> > +++ b/xen/common/sched_credit.c
> > @@ -429,6 +429,24 @@ static inline void __runq_tickle(struct
> > csched_vcpu *new)
> >      idlers_empty = cpumask_empty(&idle_mask);
> >  
> >      /*
> > +     * Exclusive pinning is when a vcpu has hard-affinity with
> > only one
> > +     * cpu, and there is no other vcpu that has hard-affinity with
> > that
> > +     * same cpu. This is infrequent, but if it happens, is for
> > achieving
> > +     * the most possible determinism, and least possible overhead
> > for
> > +     * the vcpus in question.
> > +     *
> > +     * Try to identify the vast majority of these situations, and
> > deal
> > +     * with them quickly.
> > +     */
> > +    if ( unlikely(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity) 
> > == cpu &&
> 
> Won't this check entail a full "loop" of the cpumask?  It's cheap
> enough
> if nr_cpu_ids is small; but don't we support (theoretically) 4096
> logical cpus?
> 
> It seems like having a vcpu flag that identifies a vcpu as being
> pinned
> would be a more efficient way to do this.  That way we could run this
> check once whenever the hard affinity changed, rather than every time
> we
> want to think about where to run this vcpu.
> 
> What do you think?
> 
Right. We actually should get some help from the hardware (ffs &
firends)... but I think you're right. Implementing this with a flag, as
 you're suggesting, is most likely better, and easy enough.

I'll go for that!

Regards,
Dario
George Dunlap July 21, 2017, 8:30 p.m. UTC | #3
On Fri, Jul 21, 2017 at 8:55 PM, Dario Faggioli
<dario.faggioli@citrix.com> wrote:
> On Fri, 2017-07-21 at 18:19 +0100, George Dunlap wrote:
>> On 06/23/2017 11:55 AM, Dario Faggioli wrote:
>> > diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
>> > index 4f6330e..85e014d 100644
>> > --- a/xen/common/sched_credit.c
>> > +++ b/xen/common/sched_credit.c
>> > @@ -429,6 +429,24 @@ static inline void __runq_tickle(struct
>> > csched_vcpu *new)
>> >      idlers_empty = cpumask_empty(&idle_mask);
>> >
>> >      /*
>> > +     * Exclusive pinning is when a vcpu has hard-affinity with
>> > only one
>> > +     * cpu, and there is no other vcpu that has hard-affinity with
>> > that
>> > +     * same cpu. This is infrequent, but if it happens, is for
>> > achieving
>> > +     * the most possible determinism, and least possible overhead
>> > for
>> > +     * the vcpus in question.
>> > +     *
>> > +     * Try to identify the vast majority of these situations, and
>> > deal
>> > +     * with them quickly.
>> > +     */
>> > +    if ( unlikely(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity)
>> > == cpu &&
>>
>> Won't this check entail a full "loop" of the cpumask?  It's cheap
>> enough
>> if nr_cpu_ids is small; but don't we support (theoretically) 4096
>> logical cpus?
>>
>> It seems like having a vcpu flag that identifies a vcpu as being
>> pinned
>> would be a more efficient way to do this.  That way we could run this
>> check once whenever the hard affinity changed, rather than every time
>> we
>> want to think about where to run this vcpu.
>>
>> What do you think?
>>
> Right. We actually should get some help from the hardware (ffs &
> firends)... but I think you're right. Implementing this with a flag, as
>  you're suggesting, is most likely better, and easy enough.
>
> I'll go for that!

Cool.  BTW I checked the first 5 in.

 -George
diff mbox

Patch

diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
index 4f6330e..85e014d 100644
--- a/xen/common/sched_credit.c
+++ b/xen/common/sched_credit.c
@@ -429,6 +429,24 @@  static inline void __runq_tickle(struct csched_vcpu *new)
     idlers_empty = cpumask_empty(&idle_mask);
 
     /*
+     * Exclusive pinning is when a vcpu has hard-affinity with only one
+     * cpu, and there is no other vcpu that has hard-affinity with that
+     * same cpu. This is infrequent, but if it happens, is for achieving
+     * the most possible determinism, and least possible overhead for
+     * the vcpus in question.
+     *
+     * Try to identify the vast majority of these situations, and deal
+     * with them quickly.
+     */
+    if ( unlikely(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity) == cpu &&
+                  cpumask_test_cpu(cpu, &idle_mask)) )
+    {
+        SCHED_STAT_CRANK(tickled_idle_cpu_excl);
+        __cpumask_set_cpu(cpu, &mask);
+        goto tickle;
+    }
+
+    /*
      * If the pcpu is idle, or there are no idlers and the new
      * vcpu is a higher priority than the old vcpu, run it here.
      *
@@ -524,6 +542,7 @@  static inline void __runq_tickle(struct csched_vcpu *new)
         }
     }
 
+ tickle:
     if ( !cpumask_empty(&mask) )
     {
         if ( unlikely(tb_init_done) )
diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 9814072..3a1ecbb 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -1186,7 +1186,26 @@  runq_tickle(const struct scheduler *ops, struct csched2_vcpu *new, s_time_t now)
                 cpupool_domain_cpumask(new->vcpu->domain));
 
     /*
-     * First of all, consider idle cpus, checking if we can just
+     * Exclusive pinning is when a vcpu has hard-affinity with only one
+     * cpu, and there is no other vcpu that has hard-affinity with that
+     * same cpu. This is infrequent, but if it happens, is for achieving
+     * the most possible determinism, and least possible overhead for
+     * the vcpus in question.
+     *
+     * Try to identify the vast majority of these situations, and deal
+     * with them quickly.
+     */
+    if ( unlikely(cpumask_cycle(cpu, cpumask_scratch_cpu(cpu)) == cpu &&
+                  cpumask_test_cpu(cpu, &rqd->idle) &&
+                  !cpumask_test_cpu(cpu, &rqd->tickled)) )
+    {
+        SCHED_STAT_CRANK(tickled_idle_cpu_excl);
+        ipid = cpu;
+        goto tickle;
+    }
+
+    /*
+     * Afterwards, let's consider idle cpus, checking if we can just
      * re-use the pcpu where we were running before.
      *
      * If there are cores where all the siblings are idle, consider
diff --git a/xen/include/xen/perfc_defn.h b/xen/include/xen/perfc_defn.h
index 53849af..ad914dc 100644
--- a/xen/include/xen/perfc_defn.h
+++ b/xen/include/xen/perfc_defn.h
@@ -30,6 +30,7 @@  PERFCOUNTER(vcpu_wake_runnable,     "sched: vcpu_wake_runnable")
 PERFCOUNTER(vcpu_wake_not_runnable, "sched: vcpu_wake_not_runnable")
 PERFCOUNTER(tickled_no_cpu,         "sched: tickled_no_cpu")
 PERFCOUNTER(tickled_idle_cpu,       "sched: tickled_idle_cpu")
+PERFCOUNTER(tickled_idle_cpu_excl,  "sched: tickled_idle_cpu_exclusive")
 PERFCOUNTER(tickled_busy_cpu,       "sched: tickled_busy_cpu")
 PERFCOUNTER(vcpu_check,             "sched: vcpu_check")