* [PATCH v3 0/2] sched/fair: Optimize some active balance logic
@ 2026-06-15 5:38 Xin Zhao
2026-06-15 5:38 ` [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq Xin Zhao
2026-06-15 5:38 ` [PATCH v3 2/2] sched/fair: Simplify balance_interval reset logic in sched_balance_rq() Xin Zhao
0 siblings, 2 replies; 8+ messages in thread
From: Xin Zhao @ 2026-06-15 5:38 UTC (permalink / raw)
To: vschneid, mingo, peterz, juri.lelli, vincent.guittot,
dietmar.eggemann, rostedt, bsegall, mgorman, kprateek.nayak,
aiqun.yu
Cc: linux-kernel, Xin Zhao
Active balancing needs the help by migration threads which will interrupt
task on src_rq. It has a certain impact on overall performance. Active
balancing often fails, there is a check to determine whether the current
task(say it 'curr') on src_rq can run on dst_rq. We have observed that
even that, if curr is a CFS task and on_rq is 0, the failure rate of
active balancing is very high. Below are the test data from a certain
fillback task scenario executed on a platform with 18 CPUs over 300
seconds:
total: the total count of cases that match
cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr) &&
busiest->curr->sched_class == &fair_sched_class &&
!busiest->curr->on_rq
succ/fail: the active balance success/fail cases that match
cpumask_......->on_rq
total succ fail
cpu0 domain0 00003 0 0 0
cpu0 domain1 3ffff 32 0 32
cpu1 domain0 00003 0 0 0
cpu1 domain1 3ffff 40 0 40
cpu2 domain0 0003c 3 0 3
cpu2 domain1 3ffff 6 0 6
cpu3 domain0 0003c 3 1 2
cpu3 domain1 3ffff 3 0 3
cpu4 domain0 0003c 3 0 3
cpu4 domain1 3ffff 4 0 4
cpu5 domain0 0003c 1 0 1
cpu5 domain1 3ffff 6 0 6
cpu6 domain0 003c0 39 0 39
cpu6 domain1 3ffff 36 0 36
cpu7 domain0 003c0 213 4 209
cpu7 domain1 3ffff 24 2 22
cpu8 domain0 003c0 242 16 226
cpu8 domain1 3ffff 16 0 16
cpu9 domain0 003c0 0 0 0
cpu9 domain1 3ffff 6 1 5
cpu10 domain0 03c00 58 1 57
cpu10 domain1 3ffff 0 0 0
cpu11 domain0 03c00 54 4 50
cpu11 domain1 3ffff 1 0 1
cpu12 domain0 03c00 66 1 65
cpu12 domain1 3ffff 0 0 0
cpu13 domain0 03c00 66 1 65
cpu13 domain1 3ffff 0 0 0
cpu14 domain0 3c000 0 0 0
cpu14 domain1 3ffff 57 5 52
cpu15 domain0 3c000 15 0 15
cpu15 domain1 3ffff 35 0 35
cpu16 domain0 3c000 148 3 145
cpu16 domain1 3ffff 109 1 108
cpu17 domain0 3c000 182 2 180
cpu17 domain1 3ffff 78 1 77
In __schedule(), before setting curr to next, during the execution of
pick_next_task(), sched_balance_rq() is called. It will unlock and then
re-lock the rq, creating "holes" during which other CPUs may see zero
rq->curr->on_rq. try_to_block_task() sets curr->on_rq to 0, and during the
rq lock "hole" in pick_next_task(), rq->curr has not yet been assigned to
next, resulting in curr->on_rq being seen as 0.
We do not need to perform active balancing when src_rq->curr is CFS task
but on_rq is 0, as other CFS tasks have been already checked just before.
For cases where src_rq->curr is a non-CFS task, we retain the affinity
check for dst_rq to trigger active balancing because such task is likely
to wake-up or woken-by src_rq CFS task which has similar affinity
characteristics to migrate.
Two reasons why not check sched_class and on_rq of busiest->curr with the
cpumask_test_cpu() check:
1. Let the PATCH not introduce new cases that skip logic for resetting
balance_interval to min_interval.
2. The check of whether busiest cpu has been just triggered active balance
filters a bit more cases than the check of sched_class and on_rq.
Additionally, in sched_balance_rq(), we unconditionally reset the
balance_interval to min_interval. The difference is that original logic
does not reset the balance_interval when dst_cpu softirq handler is
preempted while src_cpu successfully run the just-dispatched active
balancing, during the gaps between two need_active_balance() checks. It
seems that we haven't observed any substantial benefits from reducing the
opportunities for balance under such fluctuating conditions. So simplify
the need_active_balance() checks logic.
---
Changes in v3:
- Consider the cost by sched_class and on_rq check,
as suggested by Aiqun(Maira) Yu.
Move the check after the check of whether busiest cpu has been just
triggered active balance.
- Separate the revise of balance_interval reset part to an independent
patch, as suggested by Aiqun(Maira) Yu.
Add more details about the independent patch.
Change in v2:
- Add reason in the commit log why we can see zero rq->curr->on_rq when we
hold rq lock,
as suggested by Valentin Schneider.
- Link to v2: https://lore.kernel.org/all/20260613073228.1951105-1-jackzxcui1989@163.com/
v1:
- Link to v1: https://lore.kernel.org/all/20260603125938.1938115-1-jackzxcui1989@163.com/
Xin Zhao (2):
sched/fair: Don't trigger active lb if src_rq->curr is CFS and not
on_rq
sched/fair: Simplify balance_interval reset logic in
sched_balance_rq()
kernel/sched/fair.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-15 5:38 [PATCH v3 0/2] sched/fair: Optimize some active balance logic Xin Zhao @ 2026-06-15 5:38 ` Xin Zhao 2026-06-15 13:39 ` Valentin Schneider 2026-06-15 5:38 ` [PATCH v3 2/2] sched/fair: Simplify balance_interval reset logic in sched_balance_rq() Xin Zhao 1 sibling, 1 reply; 8+ messages in thread From: Xin Zhao @ 2026-06-15 5:38 UTC (permalink / raw) To: vschneid, mingo, peterz, juri.lelli, vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman, kprateek.nayak, aiqun.yu Cc: linux-kernel, Xin Zhao Active balancing needs the help by migration threads which will interrupt task on src_rq. It has a certain impact on overall performance. Active balancing often fails, there is a check to determine whether the current task(say it 'curr') on src_rq can run on dst_rq. We have observed that even that, if curr is a CFS task and on_rq is 0, the failure rate of active balancing is very high. Below are the test data from a certain fillback task scenario executed on a platform with 18 CPUs over 300 seconds: total: the total count of cases that match cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr) && busiest->curr->sched_class == &fair_sched_class && !busiest->curr->on_rq succ/fail: the active balance success/fail cases that match cpumask_......->on_rq total succ fail cpu0 domain0 00003 0 0 0 cpu0 domain1 3ffff 32 0 32 cpu1 domain0 00003 0 0 0 cpu1 domain1 3ffff 40 0 40 cpu2 domain0 0003c 3 0 3 cpu2 domain1 3ffff 6 0 6 cpu3 domain0 0003c 3 1 2 cpu3 domain1 3ffff 3 0 3 cpu4 domain0 0003c 3 0 3 cpu4 domain1 3ffff 4 0 4 cpu5 domain0 0003c 1 0 1 cpu5 domain1 3ffff 6 0 6 cpu6 domain0 003c0 39 0 39 cpu6 domain1 3ffff 36 0 36 cpu7 domain0 003c0 213 4 209 cpu7 domain1 3ffff 24 2 22 cpu8 domain0 003c0 242 16 226 cpu8 domain1 3ffff 16 0 16 cpu9 domain0 003c0 0 0 0 cpu9 domain1 3ffff 6 1 5 cpu10 domain0 03c00 58 1 57 cpu10 domain1 3ffff 0 0 0 cpu11 domain0 03c00 54 4 50 cpu11 domain1 3ffff 1 0 1 cpu12 domain0 03c00 66 1 65 cpu12 domain1 3ffff 0 0 0 cpu13 domain0 03c00 66 1 65 cpu13 domain1 3ffff 0 0 0 cpu14 domain0 3c000 0 0 0 cpu14 domain1 3ffff 57 5 52 cpu15 domain0 3c000 15 0 15 cpu15 domain1 3ffff 35 0 35 cpu16 domain0 3c000 148 3 145 cpu16 domain1 3ffff 109 1 108 cpu17 domain0 3c000 182 2 180 cpu17 domain1 3ffff 78 1 77 In __schedule(), before setting curr to next, during the execution of pick_next_task(), sched_balance_rq() is called. It will unlock and then re-lock the rq, creating "holes" during which other CPUs may see zero rq->curr->on_rq. try_to_block_task() sets curr->on_rq to 0, and during the rq lock "hole" in pick_next_task(), rq->curr has not yet been assigned to next, resulting in curr->on_rq being seen as 0. We do not need to perform active balancing when src_rq->curr is CFS task but on_rq is 0, as other CFS tasks have been already checked just before. For cases where src_rq->curr is a non-CFS task, we retain the affinity check for dst_rq to trigger active balancing because such task is likely to wake-up or woken-by src_rq CFS task which has similar affinity characteristics to migrate. Two reasons why not check sched_class and on_rq of busiest->curr with the cpumask_test_cpu() check: 1. Let the PATCH not introduce new cases that skip logic for resetting balance_interval to min_interval. 2. The check of whether busiest cpu has been just triggered active balance filters a bit more cases than the check of sched_class and on_rq. Signed-off-by: Xin Zhao <jackzxcui1989@163.com> --- Change in v3: - Consider the cost by sched_class and on_rq check, as suggested by Aiqun(Maira) Yu. Move the check after the check of whether busiest cpu has been just triggered active balance. Change in v2: - Add reason in the commit log why we can see zero rq->curr->on_rq when we hold rq lock, as suggested by Valentin Schneider. - Link to v2: https://lore.kernel.org/all/20260613073228.1951105-1-jackzxcui1989@163.com/ v1: - Link to v1: https://lore.kernel.org/all/20260603125938.1938115-1-jackzxcui1989@163.com/ --- kernel/sched/fair.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index b5819c489..1c5043629 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -13436,7 +13436,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, * ->active_balance_work. Once set, it's cleared * only after active load balance is finished. */ - if (!busiest->active_balance) { + if (!busiest->active_balance && + !(busiest->curr->sched_class == &fair_sched_class && + !busiest->curr->on_rq)) { busiest->active_balance = 1; busiest->push_cpu = this_cpu; active_balance = 1; -- 2.34.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-15 5:38 ` [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq Xin Zhao @ 2026-06-15 13:39 ` Valentin Schneider 2026-06-15 13:57 ` Phil Auld 2026-06-15 14:09 ` Xin Zhao 0 siblings, 2 replies; 8+ messages in thread From: Valentin Schneider @ 2026-06-15 13:39 UTC (permalink / raw) To: Xin Zhao, mingo, peterz, juri.lelli, vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman, kprateek.nayak, aiqun.yu Cc: linux-kernel, Xin Zhao On 15/06/26 13:38, Xin Zhao wrote: > Active balancing needs the help by migration threads which will interrupt > task on src_rq. It has a certain impact on overall performance. Active > balancing often fails, there is a check to determine whether the current > task(say it 'curr') on src_rq can run on dst_rq. We have observed that > even that, if curr is a CFS task and on_rq is 0, the failure rate of > active balancing is very high. Below are the test data from a certain > fillback task scenario executed on a platform with 18 CPUs over 300 > seconds: > > total: the total count of cases that match > cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr) && > busiest->curr->sched_class == &fair_sched_class && > !busiest->curr->on_rq > succ/fail: the active balance success/fail cases that match > cpumask_......->on_rq > > total succ fail > cpu0 domain0 00003 0 0 0 > cpu0 domain1 3ffff 32 0 32 > cpu1 domain0 00003 0 0 0 > cpu1 domain1 3ffff 40 0 40 > cpu2 domain0 0003c 3 0 3 > cpu2 domain1 3ffff 6 0 6 > cpu3 domain0 0003c 3 1 2 > cpu3 domain1 3ffff 3 0 3 > cpu4 domain0 0003c 3 0 3 > cpu4 domain1 3ffff 4 0 4 > cpu5 domain0 0003c 1 0 1 > cpu5 domain1 3ffff 6 0 6 > cpu6 domain0 003c0 39 0 39 > cpu6 domain1 3ffff 36 0 36 > cpu7 domain0 003c0 213 4 209 > cpu7 domain1 3ffff 24 2 22 > cpu8 domain0 003c0 242 16 226 > cpu8 domain1 3ffff 16 0 16 > cpu9 domain0 003c0 0 0 0 > cpu9 domain1 3ffff 6 1 5 > cpu10 domain0 03c00 58 1 57 > cpu10 domain1 3ffff 0 0 0 > cpu11 domain0 03c00 54 4 50 > cpu11 domain1 3ffff 1 0 1 > cpu12 domain0 03c00 66 1 65 > cpu12 domain1 3ffff 0 0 0 > cpu13 domain0 03c00 66 1 65 > cpu13 domain1 3ffff 0 0 0 > cpu14 domain0 3c000 0 0 0 > cpu14 domain1 3ffff 57 5 52 > cpu15 domain0 3c000 15 0 15 > cpu15 domain1 3ffff 35 0 35 > cpu16 domain0 3c000 148 3 145 > cpu16 domain1 3ffff 109 1 108 > cpu17 domain0 3c000 182 2 180 > cpu17 domain1 3ffff 78 1 77 > > In __schedule(), before setting curr to next, during the execution of > pick_next_task(), sched_balance_rq() is called. It will unlock and then > re-lock the rq, creating "holes" during which other CPUs may see zero > rq->curr->on_rq. try_to_block_task() sets curr->on_rq to 0, and during the > rq lock "hole" in pick_next_task(), rq->curr has not yet been assigned to > next, resulting in curr->on_rq being seen as 0. > Aaah, it's a load balance shaped hole... Urgh, okay I see it now, thanks. > We do not need to perform active balancing when src_rq->curr is CFS task > but on_rq is 0, as other CFS tasks have been already checked just before. > For cases where src_rq->curr is a non-CFS task, we retain the affinity > check for dst_rq to trigger active balancing because such task is likely > to wake-up or woken-by src_rq CFS task which has similar affinity > characteristics to migrate. > > Two reasons why not check sched_class and on_rq of busiest->curr with the > cpumask_test_cpu() check: > 1. Let the PATCH not introduce new cases that skip logic for resetting > balance_interval to min_interval. > 2. The check of whether busiest cpu has been just triggered active balance > filters a bit more cases than the check of sched_class and on_rq. > > Signed-off-by: Xin Zhao <jackzxcui1989@163.com> > --- > > Change in v3: > - Consider the cost by sched_class and on_rq check, > as suggested by Aiqun(Maira) Yu. > Move the check after the check of whether busiest cpu has been just > triggered active balance. > > Change in v2: > - Add reason in the commit log why we can see zero rq->curr->on_rq when we > hold rq lock, > as suggested by Valentin Schneider. > - Link to v2: https://lore.kernel.org/all/20260613073228.1951105-1-jackzxcui1989@163.com/ > > v1: > - Link to v1: https://lore.kernel.org/all/20260603125938.1938115-1-jackzxcui1989@163.com/ > --- > kernel/sched/fair.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index b5819c489..1c5043629 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -13436,7 +13436,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > * ->active_balance_work. Once set, it's cleared > * only after active load balance is finished. > */ > - if (!busiest->active_balance) { > + if (!busiest->active_balance && > + !(busiest->curr->sched_class == &fair_sched_class && > + !busiest->curr->on_rq)) { This should be commented; I restructured this a little, it's one more label but it reads better to me, what do you think? --- diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d78467ec6ee13..a0ac31a3be988 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -13482,12 +13482,22 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, * ->active_balance_work. Once set, it's cleared * only after active load balance is finished. */ - if (!busiest->active_balance) { - busiest->active_balance = 1; - busiest->push_cpu = this_cpu; - active_balance = 1; - } + if (busiest->active_balance) + goto no_active_balance; + /* + * @busiest dropped its rq_lock in the middle of + * scheduling out its ->curr task (->on_rq := 0), no + * need to forcefully punt it away with active balance. + */ + if ((busiest->curr->sched_class == &fair_sched_class) && + !busiest->curr->on_rq) + goto no_active_balance; + + busiest->active_balance = 1; + busiest->push_cpu = this_cpu; + active_balance = 1; +no_active_balance: preempt_disable(); raw_spin_rq_unlock_irqrestore(busiest, flags); if (active_balance) { ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-15 13:39 ` Valentin Schneider @ 2026-06-15 13:57 ` Phil Auld 2026-06-15 14:09 ` Xin Zhao 1 sibling, 0 replies; 8+ messages in thread From: Phil Auld @ 2026-06-15 13:57 UTC (permalink / raw) To: Valentin Schneider Cc: Xin Zhao, mingo, peterz, juri.lelli, vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman, kprateek.nayak, aiqun.yu, linux-kernel Hi, On Mon, Jun 15, 2026 at 03:39:22PM +0200 Valentin Schneider wrote: > On 15/06/26 13:38, Xin Zhao wrote: > > Active balancing needs the help by migration threads which will interrupt > > task on src_rq. It has a certain impact on overall performance. Active > > balancing often fails, there is a check to determine whether the current > > task(say it 'curr') on src_rq can run on dst_rq. We have observed that > > even that, if curr is a CFS task and on_rq is 0, the failure rate of > > active balancing is very high. Below are the test data from a certain > > fillback task scenario executed on a platform with 18 CPUs over 300 > > seconds: > > > > total: the total count of cases that match > > cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr) && > > busiest->curr->sched_class == &fair_sched_class && > > !busiest->curr->on_rq > > succ/fail: the active balance success/fail cases that match > > cpumask_......->on_rq > > > > total succ fail > > cpu0 domain0 00003 0 0 0 > > cpu0 domain1 3ffff 32 0 32 > > cpu1 domain0 00003 0 0 0 > > cpu1 domain1 3ffff 40 0 40 > > cpu2 domain0 0003c 3 0 3 > > cpu2 domain1 3ffff 6 0 6 > > cpu3 domain0 0003c 3 1 2 > > cpu3 domain1 3ffff 3 0 3 > > cpu4 domain0 0003c 3 0 3 > > cpu4 domain1 3ffff 4 0 4 > > cpu5 domain0 0003c 1 0 1 > > cpu5 domain1 3ffff 6 0 6 > > cpu6 domain0 003c0 39 0 39 > > cpu6 domain1 3ffff 36 0 36 > > cpu7 domain0 003c0 213 4 209 > > cpu7 domain1 3ffff 24 2 22 > > cpu8 domain0 003c0 242 16 226 > > cpu8 domain1 3ffff 16 0 16 > > cpu9 domain0 003c0 0 0 0 > > cpu9 domain1 3ffff 6 1 5 > > cpu10 domain0 03c00 58 1 57 > > cpu10 domain1 3ffff 0 0 0 > > cpu11 domain0 03c00 54 4 50 > > cpu11 domain1 3ffff 1 0 1 > > cpu12 domain0 03c00 66 1 65 > > cpu12 domain1 3ffff 0 0 0 > > cpu13 domain0 03c00 66 1 65 > > cpu13 domain1 3ffff 0 0 0 > > cpu14 domain0 3c000 0 0 0 > > cpu14 domain1 3ffff 57 5 52 > > cpu15 domain0 3c000 15 0 15 > > cpu15 domain1 3ffff 35 0 35 > > cpu16 domain0 3c000 148 3 145 > > cpu16 domain1 3ffff 109 1 108 > > cpu17 domain0 3c000 182 2 180 > > cpu17 domain1 3ffff 78 1 77 > > > > In __schedule(), before setting curr to next, during the execution of > > pick_next_task(), sched_balance_rq() is called. It will unlock and then > > re-lock the rq, creating "holes" during which other CPUs may see zero > > rq->curr->on_rq. try_to_block_task() sets curr->on_rq to 0, and during the > > rq lock "hole" in pick_next_task(), rq->curr has not yet been assigned to > > next, resulting in curr->on_rq being seen as 0. > > > > Aaah, it's a load balance shaped hole... Urgh, okay I see it now, thanks. > > > We do not need to perform active balancing when src_rq->curr is CFS task > > but on_rq is 0, as other CFS tasks have been already checked just before. > > For cases where src_rq->curr is a non-CFS task, we retain the affinity > > check for dst_rq to trigger active balancing because such task is likely > > to wake-up or woken-by src_rq CFS task which has similar affinity > > characteristics to migrate. > > > > Two reasons why not check sched_class and on_rq of busiest->curr with the > > cpumask_test_cpu() check: > > 1. Let the PATCH not introduce new cases that skip logic for resetting > > balance_interval to min_interval. > > 2. The check of whether busiest cpu has been just triggered active balance > > filters a bit more cases than the check of sched_class and on_rq. > > > > Signed-off-by: Xin Zhao <jackzxcui1989@163.com> > > --- > > > > Change in v3: > > - Consider the cost by sched_class and on_rq check, > > as suggested by Aiqun(Maira) Yu. > > Move the check after the check of whether busiest cpu has been just > > triggered active balance. > > > > Change in v2: > > - Add reason in the commit log why we can see zero rq->curr->on_rq when we > > hold rq lock, > > as suggested by Valentin Schneider. > > - Link to v2: https://lore.kernel.org/all/20260613073228.1951105-1-jackzxcui1989@163.com/ > > > > v1: > > - Link to v1: https://lore.kernel.org/all/20260603125938.1938115-1-jackzxcui1989@163.com/ > > --- > > kernel/sched/fair.c | 4 +++- > > 1 file changed, 3 insertions(+), 1 deletion(-) > > > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > > index b5819c489..1c5043629 100644 > > --- a/kernel/sched/fair.c > > +++ b/kernel/sched/fair.c > > @@ -13436,7 +13436,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > > * ->active_balance_work. Once set, it's cleared > > * only after active load balance is finished. > > */ > > - if (!busiest->active_balance) { > > + if (!busiest->active_balance && > > + !(busiest->curr->sched_class == &fair_sched_class && > > + !busiest->curr->on_rq)) { > > This should be commented; I restructured this a little, it's one more label > but it reads better to me, what do you think? This below does look better to me as well, fwiw. Cheers, Phil > --- > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index d78467ec6ee13..a0ac31a3be988 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -13482,12 +13482,22 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > * ->active_balance_work. Once set, it's cleared > * only after active load balance is finished. > */ > - if (!busiest->active_balance) { > - busiest->active_balance = 1; > - busiest->push_cpu = this_cpu; > - active_balance = 1; > - } > + if (busiest->active_balance) > + goto no_active_balance; > > + /* > + * @busiest dropped its rq_lock in the middle of > + * scheduling out its ->curr task (->on_rq := 0), no > + * need to forcefully punt it away with active balance. > + */ > + if ((busiest->curr->sched_class == &fair_sched_class) && > + !busiest->curr->on_rq) > + goto no_active_balance; > + > + busiest->active_balance = 1; > + busiest->push_cpu = this_cpu; > + active_balance = 1; > +no_active_balance: > preempt_disable(); > raw_spin_rq_unlock_irqrestore(busiest, flags); > if (active_balance) { > > -- ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-15 13:39 ` Valentin Schneider 2026-06-15 13:57 ` Phil Auld @ 2026-06-15 14:09 ` Xin Zhao 2026-06-16 3:06 ` Aiqun(Maria) Yu 1 sibling, 1 reply; 8+ messages in thread From: Xin Zhao @ 2026-06-15 14:09 UTC (permalink / raw) To: vschneid Cc: aiqun.yu, bsegall, dietmar.eggemann, jackzxcui1989, juri.lelli, kprateek.nayak, linux-kernel, mgorman, mingo, peterz, rostedt, vincent.guittot On Mon, 15 Jun 2026 15:39:22 +0200 Valentin Schneider <vschneid@redhat.com> wrote: > > @@ -13436,7 +13436,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > > * ->active_balance_work. Once set, it's cleared > > * only after active load balance is finished. > > */ > > - if (!busiest->active_balance) { > > + if (!busiest->active_balance && > > + !(busiest->curr->sched_class == &fair_sched_class && > > + !busiest->curr->on_rq)) { > > This should be commented; I restructured this a little, it's one more label > but it reads better to me, what do you think? :) Thank you for your changes; it looks much better now, and the necessary comments have been added. > --- > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index d78467ec6ee13..a0ac31a3be988 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -13482,12 +13482,22 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > * ->active_balance_work. Once set, it's cleared > * only after active load balance is finished. > */ > - if (!busiest->active_balance) { > - busiest->active_balance = 1; > - busiest->push_cpu = this_cpu; > - active_balance = 1; > - } > + if (busiest->active_balance) > + goto no_active_balance; > > + /* > + * @busiest dropped its rq_lock in the middle of > + * scheduling out its ->curr task (->on_rq := 0), no > + * need to forcefully punt it away with active balance. > + */ > + if ((busiest->curr->sched_class == &fair_sched_class) && > + !busiest->curr->on_rq) > + goto no_active_balance; > + > + busiest->active_balance = 1; > + busiest->push_cpu = this_cpu; > + active_balance = 1; > +no_active_balance: > preempt_disable(); > raw_spin_rq_unlock_irqrestore(busiest, flags); > if (active_balance) { Thanks Xin Zhao ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-15 14:09 ` Xin Zhao @ 2026-06-16 3:06 ` Aiqun(Maria) Yu 2026-06-16 4:07 ` Xin Zhao 0 siblings, 1 reply; 8+ messages in thread From: Aiqun(Maria) Yu @ 2026-06-16 3:06 UTC (permalink / raw) To: Xin Zhao, vschneid Cc: bsegall, dietmar.eggemann, juri.lelli, kprateek.nayak, linux-kernel, mgorman, mingo, peterz, rostedt, vincent.guittot On 6/15/2026 10:09 PM, Xin Zhao wrote: > On Mon, 15 Jun 2026 15:39:22 +0200 Valentin Schneider <vschneid@redhat.com> wrote: > >>> @@ -13436,7 +13436,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, >>> * ->active_balance_work. Once set, it's cleared >>> * only after active load balance is finished. >>> */ >>> - if (!busiest->active_balance) { >>> + if (!busiest->active_balance && >>> + !(busiest->curr->sched_class == &fair_sched_class && >>> + !busiest->curr->on_rq)) { >> >> This should be commented; I restructured this a little, it's one more label >> but it reads better to me, what do you think? > > :) Thank you for your changes; it looks much better now, and the necessary > comments have been added. This format looks better. > >> --- >> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c >> index d78467ec6ee13..a0ac31a3be988 100644 >> --- a/kernel/sched/fair.c >> +++ b/kernel/sched/fair.c >> @@ -13482,12 +13482,22 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, >> * ->active_balance_work. Once set, it's cleared >> * only after active load balance is finished. >> */ >> - if (!busiest->active_balance) { >> - busiest->active_balance = 1; >> - busiest->push_cpu = this_cpu; >> - active_balance = 1; >> - } >> + if (busiest->active_balance) >> + goto no_active_balance; >> >> + /* >> + * @busiest dropped its rq_lock in the middle of >> + * scheduling out its ->curr task (->on_rq := 0), no >> + * need to forcefully punt it away with active balance. >> + */ >> + if ((busiest->curr->sched_class == &fair_sched_class) && >> + !busiest->curr->on_rq) Still have the doubt why need to do active load balance when the current is not CFS. And busiest->curr->on_rq==0 case only. Is it should be like: if ((busiest->curr->sched_class == &fair_sched_class) || unlikely(!task_on_rq_queued(busiest->curr))); if busiest->curr->on_rq==2 (TASK_ON_RQ_MIGRATING), it is no need to do active_balance as well. >> + goto no_active_balance; >> + >> + busiest->active_balance = 1; >> + busiest->push_cpu = this_cpu; >> + active_balance = 1; >> +no_active_balance: >> preempt_disable(); >> raw_spin_rq_unlock_irqrestore(busiest, flags); >> if (active_balance) { > > Thanks > Xin Zhao > -- Thx and BRs, Aiqun(Maria) Yu ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq 2026-06-16 3:06 ` Aiqun(Maria) Yu @ 2026-06-16 4:07 ` Xin Zhao 0 siblings, 0 replies; 8+ messages in thread From: Xin Zhao @ 2026-06-16 4:07 UTC (permalink / raw) To: aiqun.yu Cc: bsegall, dietmar.eggemann, jackzxcui1989, juri.lelli, kprateek.nayak, linux-kernel, mgorman, mingo, peterz, rostedt, vincent.guittot, vschneid On Tue, 16 Jun 2026 11:06:54 +0800 "Aiqun(Maria) Yu" <aiqun.yu@oss.qualcomm.com> wrote: > >> + * need to forcefully punt it away with active balance. > >> + */ > >> + if ((busiest->curr->sched_class == &fair_sched_class) && > >> + !busiest->curr->on_rq) > > Still have the doubt why need to do active load balance when the current > is not CFS. And busiest->curr->on_rq==0 case only. > > Is it should be like: > if ((busiest->curr->sched_class == &fair_sched_class) || > unlikely(!task_on_rq_queued(busiest->curr))); The platform I am using is quite close to actual usage, and the tasks bound to different CPUs and different scheduling domains vary significantly. From my data, there isn't a single CPU with an active balance success rate below 50% under such scenarios. As for your earlier comment that "just do detach_task and attach_task and the success rate will be 100%", I believe you should take a closer look at the implementation of active_load_balance_cpu_stop. That should make it clear where the statistical code I previously sent you is located, instead of simply questioning my approach of performing an ineffective "detach_task and attach_task" operation to artificially inflate the success rate during testing. Regarding why the success rate of active balance is so high in this case, I have my own reasonable explanations, and I prefer not to repeat them over and over. > if busiest->curr->on_rq==2 (TASK_ON_RQ_MIGRATING), it is no need to do > active_balance as well. There is a slight difference for the compiler between comparing == 1 and comparing != 0. From my current understanding, comparing to a non-zero value is generally faster than comparing to a specific number in most of arch. I have previously tested whether on_rq would ever be equal to 2 and, over a long period of time, I did not encounter a single instance where on_rq was 2. This at least indicates that the probability is extremely low, and it may even be theoretically impossible for such a situation to occur. Thanks Xin Zhao ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 2/2] sched/fair: Simplify balance_interval reset logic in sched_balance_rq() 2026-06-15 5:38 [PATCH v3 0/2] sched/fair: Optimize some active balance logic Xin Zhao 2026-06-15 5:38 ` [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq Xin Zhao @ 2026-06-15 5:38 ` Xin Zhao 1 sibling, 0 replies; 8+ messages in thread From: Xin Zhao @ 2026-06-15 5:38 UTC (permalink / raw) To: vschneid, mingo, peterz, juri.lelli, vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman, kprateek.nayak, aiqun.yu Cc: linux-kernel, Xin Zhao In sched_balance_rq(), it is possible to call need_active_balance() twice in quick succession, which is not appropriate. There are two conditions in sched_balance_rq() that reset balance_interval to min_interval, one is when the local variable active_balance is 0, and the other is when need_active_balance() returns a non-zero value. The local variable active_balance is initialized to 0. Therefore, the only situation in which balance_interval can be reset to min_interval is if need_active_balance() has been executed once, marking the local variable active_balance as 1, and then the second call to need_active_balance() returns 0. In other words, the case is that during the interval between two close calls to need_active_balance(), busiest rq completes the recently dispatched active balance stop work, which is quite rare. There are mainly two scenarios that lead to reaching sched_balance_rq(): one is the newly idle balance triggered by __schedule(), and the other is the periodic balance logic controlled by sd->balance_interval or nohz.next_balance, which ultimately executes in the softirq context. The vast majority of cases executing sched_balance_rq() in the system fall under the first scenario. During the execution of __schedule(), preemption is disabled, so the interval between two checks of need_active_balance() in this case will not be long. Thus, before applying this patch, balance_interval would only be unlikely to reset to min_interval during the periodic balance logic, which is relatively much more less frequent than newly balance. In the case which is in softirq context, the execution of the two need_active_balance() checks can indeed be preempted by other tasks, leading to a longer interval between the two checks. However, there is no evidence to suggest that not resetting min_interval in these low-probability cases caused by scheduling preemption offers any significant benefits. It would be better to simplify this complex reset logic for balance_interval to an unconditional reset. Signed-off-by: Xin Zhao <jackzxcui1989@163.com> --- kernel/sched/fair.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1c5043629..b562a610b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -13457,10 +13457,8 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, sd->nr_balance_failed = 0; } - if (likely(!active_balance) || need_active_balance(&env)) { - /* We were unbalanced, so reset the balancing interval */ - sd->balance_interval = sd->min_interval; - } + /* We were unbalanced, so reset the balancing interval */ + sd->balance_interval = sd->min_interval; goto out; -- 2.34.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-06-16 4:08 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-06-15 5:38 [PATCH v3 0/2] sched/fair: Optimize some active balance logic Xin Zhao 2026-06-15 5:38 ` [PATCH v3 1/2] sched/fair: Don't trigger active lb if src_rq->curr is CFS and not on_rq Xin Zhao 2026-06-15 13:39 ` Valentin Schneider 2026-06-15 13:57 ` Phil Auld 2026-06-15 14:09 ` Xin Zhao 2026-06-16 3:06 ` Aiqun(Maria) Yu 2026-06-16 4:07 ` Xin Zhao 2026-06-15 5:38 ` [PATCH v3 2/2] sched/fair: Simplify balance_interval reset logic in sched_balance_rq() Xin Zhao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®