Idle load balancer is kicked off only after time check. So move
the atomic read after the time check to avoid the overhead.
If there are no nohz CPUs and next_blocked has passed, then there
will be one additional stats based load balancing which would set the
has_blocked_load to 0. It shouldn't make a difference.
Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
---
kernel/sched/fair.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7377f9117501..cd1c78d2c272 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -12447,13 +12447,6 @@ static void nohz_balancer_kick(struct rq *rq)
*/
nohz_balance_exit_idle(rq);
- /*
- * None are in tickless mode and hence no need for NOHZ idle load
- * balancing:
- */
- if (likely(!atomic_read(&nohz.nr_cpus)))
- return;
-
if (READ_ONCE(nohz.has_blocked_load) &&
time_after(now, READ_ONCE(nohz.next_blocked)))
flags = NOHZ_STATS_KICK;
@@ -12461,6 +12454,13 @@ static void nohz_balancer_kick(struct rq *rq)
if (time_before(now, nohz.next_balance))
goto out;
+ /*
+ * None are in tickless mode and hence no need for NOHZ idle load
+ * balancing:
+ */
+ if (likely(!atomic_read(&nohz.nr_cpus)))
+ return;
+
if (rq->nr_running >= 2) {
flags = NOHZ_STATS_KICK | NOHZ_BALANCE_KICK;
goto out;
--
2.47.3
On Fri, Jan 02, 2026 at 06:17:42PM +0530, Shrikanth Hegde wrote:
> Idle load balancer is kicked off only after time check. So move
> the atomic read after the time check to avoid the overhead.
Presumably this is because the nr_cpus field is more contended than the
next_balance field; but aren't they in the same cacheline? That is,
*what* !??!
> If there are no nohz CPUs and next_blocked has passed, then there
> will be one additional stats based load balancing which would set the
> has_blocked_load to 0. It shouldn't make a difference.
>
> Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
> ---
> kernel/sched/fair.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 7377f9117501..cd1c78d2c272 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -12447,13 +12447,6 @@ static void nohz_balancer_kick(struct rq *rq)
> */
> nohz_balance_exit_idle(rq);
>
> - /*
> - * None are in tickless mode and hence no need for NOHZ idle load
> - * balancing:
> - */
> - if (likely(!atomic_read(&nohz.nr_cpus)))
> - return;
> -
> if (READ_ONCE(nohz.has_blocked_load) &&
> time_after(now, READ_ONCE(nohz.next_blocked)))
> flags = NOHZ_STATS_KICK;
> @@ -12461,6 +12454,13 @@ static void nohz_balancer_kick(struct rq *rq)
> if (time_before(now, nohz.next_balance))
> goto out;
>
> + /*
> + * None are in tickless mode and hence no need for NOHZ idle load
> + * balancing:
> + */
> + if (likely(!atomic_read(&nohz.nr_cpus)))
> + return;
> +
> if (rq->nr_running >= 2) {
> flags = NOHZ_STATS_KICK | NOHZ_BALANCE_KICK;
> goto out;
> --
> 2.47.3
>
Hi Peter.
On 1/6/26 9:20 PM, Peter Zijlstra wrote:
> On Fri, Jan 02, 2026 at 06:17:42PM +0530, Shrikanth Hegde wrote:
>> Idle load balancer is kicked off only after time check. So move
>> the atomic read after the time check to avoid the overhead.
>
> Presumably this is because the nr_cpus field is more contended than the
> next_balance field; but aren't they in the same cacheline? That is,
> *what* !??!
Main reason for cacheline contention is nr_cpus in nohz struct.
Other one is idle_cpus_mask, but that is in different
cacheline itself(most of the time)
This patch is not due to next_balance being contended. It is
simply to check the value when we are sure time has passed to
attempt NOHZ balance again.
>
>> If there are no nohz CPUs and next_blocked has passed, then there
>> will be one additional stats based load balancing which would set the
>> has_blocked_load to 0. It shouldn't make a difference.
>>
>> Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
>> ---
>> kernel/sched/fair.c | 14 +++++++-------
>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>
>> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
>> index 7377f9117501..cd1c78d2c272 100644
>> --- a/kernel/sched/fair.c
>> +++ b/kernel/sched/fair.c
>> @@ -12447,13 +12447,6 @@ static void nohz_balancer_kick(struct rq *rq)
>> */
>> nohz_balance_exit_idle(rq);
>>
>> - /*
>> - * None are in tickless mode and hence no need for NOHZ idle load
>> - * balancing:
>> - */
>> - if (likely(!atomic_read(&nohz.nr_cpus)))
>> - return;
>> -
>> if (READ_ONCE(nohz.has_blocked_load) &&
>> time_after(now, READ_ONCE(nohz.next_blocked)))
>> flags = NOHZ_STATS_KICK;
>> @@ -12461,6 +12454,13 @@ static void nohz_balancer_kick(struct rq *rq)
>> if (time_before(now, nohz.next_balance))
>> goto out;
>>
>> + /*
>> + * None are in tickless mode and hence no need for NOHZ idle load
>> + * balancing:
>> + */
>> + if (likely(!atomic_read(&nohz.nr_cpus)))
>> + return;
>> +
>> if (rq->nr_running >= 2) {
>> flags = NOHZ_STATS_KICK | NOHZ_BALANCE_KICK;
>> goto out;
>> --
>> 2.47.3
>>
© 2016 - 2026 Red Hat, Inc.