2022-02-17 17:17:50

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Thu, Feb 17, 2022 at 02:26:15PM +0000, Aaron Tomlin wrote:
> On Thu 2022-02-17 13:47 +0100, Frederic Weisbecker wrote:
> > So, to make sure I understand, the issue is that with nohz_full, we may
> > well enter into the idle loop with the tick already stopped. We may also
> > exit from idle without restarting the tick (again only with nohz_full). And
> > so this can cause the vmstat to not be flushed upon idle entry. Right?
>
> Hi Frederic,
>
> Yes - this is exactly it.
>
> > > A customer provided some evidence which indicates that the idle tick was
> > > stopped; albeit, CPU-specific vmstat counters still remained populated.
> > > Thus one can only assume quiet_vmstat() was not invoked on return to the
> > > idle loop.
> > >
> > > Unfortunately, I suspect this divergence might erroneously prevent a
> > > reclaim attempt by kswapd. If the number of zone specific free pages are
> > > below their per-cpu drift value then zone_page_state_snapshot() is used to
> > > compute a more accurate view of the aforementioned statistic.
> > > Thus any task blocked on the NUMA node specific pfmemalloc_wait queue will
> > > be unable to make significant progress via direct reclaim unless it is
> > > killed after being woken up by kswapd (see throttle_direct_reclaim()).
> > > That being said, eventually reclaim should give up if the conditions are
> > > correct, no?
>
> > Now if quiet_vmstat() isn't called, the vmstat_work should fix this later,
> > right? Or does that happen too late perhaps?
>
> If I understand correctly, in the context of nohz_full, since such work is
> deferred, it will only be handled in a scenario when the periodic/or
> scheduling-clock tick is enabled i.e. the timer was reprogrammed on exit
> from idle.

Oh I see, it's a deferrable delayed work...
Then I can see two other issues:

1) Can an interrupt in idle modify the vmstat and thus trigger the need to
flush it? I believe it's the case and then the problem goes beyond nohz_full
because if the idle interrupt fired while the tick is stopped and didn't set
TIF_RESCHED, we go back to sleep without calling quiet_vmstat().

2) What if we are running task A in kernel mode while the tick is stopped
(nohz_full). Task A modifies the vmstat and goes to userspace for a long
while.

Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
should really be about dynticks-idle only and not dynticks-full. I've always
been afraid about enforcing that rule though because that would break old
noise-free setups. But perhaps I should...


2022-02-18 13:46:07

by Aaron Tomlin

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Thu 2022-02-17 17:32 +0100, Frederic Weisbecker wrote:
> > If I understand correctly, in the context of nohz_full, since such work is
> > deferred, it will only be handled in a scenario when the periodic/or
> > scheduling-clock tick is enabled i.e. the timer was reprogrammed on exit
> > from idle.
>
> Oh I see, it's a deferrable delayed work...
> Then I can see two other issues:
>
> 1) Can an interrupt in idle modify the vmstat and thus trigger the need to
> flush it? I believe it's the case and then the problem goes beyond nohz_full
> because if the idle interrupt fired while the tick is stopped and didn't set
> TIF_RESCHED, we go back to sleep without calling quiet_vmstat().

Yes: e.g. a nohz_full CPU, in idle code, could indeed receive a reschedule
IPI; re-enable local IRQs and generic idle code sees the TIF_NEED_RESCHED
flag against the idle task. Additionally, the selected task could
indirectly released a few pages [to satisfy a low-memory condition] and
modify CPU-specific vmstat data i.e. vm_stat_diff[NR_FREE_PAGES].


> 2) What if we are running task A in kernel mode while the tick is stopped
> (nohz_full). Task A modifies the vmstat and goes to userspace for a long
> while.
> Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
> should really be about dynticks-idle only and not dynticks-full. I've always
> been afraid about enforcing that rule though because that would break old
> noise-free setups. But perhaps I should...

If I understand correctly, I agree. For the latter case, nothing can be
done unfortunately since the scheduling-clock tick is stopped.


Kind regards,

--
Aaron Tomlin

2022-02-19 16:03:17

by Aaron Tomlin

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Fri 2022-02-18 12:54 +0000, Aaron Tomlin wrote:
> On Thu 2022-02-17 17:32 +0100, Frederic Weisbecker wrote:
> > > If I understand correctly, in the context of nohz_full, since such work is
> > > deferred, it will only be handled in a scenario when the periodic/or
> > > scheduling-clock tick is enabled i.e. the timer was reprogrammed on exit
> > > from idle.
> >
> > Oh I see, it's a deferrable delayed work...
> > Then I can see two other issues:
> >
> > 1) Can an interrupt in idle modify the vmstat and thus trigger the need to
> > flush it? I believe it's the case and then the problem goes beyond nohz_full
> > because if the idle interrupt fired while the tick is stopped and didn't set
> > TIF_RESCHED, we go back to sleep without calling quiet_vmstat().
>
> Yes: e.g. a nohz_full CPU, in idle code, could indeed receive a reschedule
> IPI; re-enable local IRQs and generic idle code sees the TIF_NEED_RESCHED
> flag against the idle task. Additionally, the selected task could
> indirectly released a few pages [to satisfy a low-memory condition] and
> modify CPU-specific vmstat data i.e. vm_stat_diff[NR_FREE_PAGES].
>
>
> > 2) What if we are running task A in kernel mode while the tick is stopped
> > (nohz_full). Task A modifies the vmstat and goes to userspace for a long
> > while.
> > Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
> > should really be about dynticks-idle only and not dynticks-full. I've always
> > been afraid about enforcing that rule though because that would break old
> > noise-free setups. But perhaps I should...
>
> If I understand correctly, I agree. For the latter case, nothing can be
> done unfortunately since the scheduling-clock tick is stopped.

Hi Frederic,

As far as I understand, in the context of nohz_full, options are indeed
limited; albeit, if we can ensure CPU-specific vmstat data is folded on
return to idle [when required] then this should be good enough.


Kind regards,

--
Aaron Tomlin

2022-02-24 15:13:36

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Sat, Feb 19, 2022 at 03:46:16PM +0000, Aaron Tomlin wrote:
> On Fri 2022-02-18 12:54 +0000, Aaron Tomlin wrote:
> > On Thu 2022-02-17 17:32 +0100, Frederic Weisbecker wrote:
> > > > If I understand correctly, in the context of nohz_full, since such work is
> > > > deferred, it will only be handled in a scenario when the periodic/or
> > > > scheduling-clock tick is enabled i.e. the timer was reprogrammed on exit
> > > > from idle.
> > >
> > > Oh I see, it's a deferrable delayed work...
> > > Then I can see two other issues:
> > >
> > > 1) Can an interrupt in idle modify the vmstat and thus trigger the need to
> > > flush it?

Yes. Page allocation and page freeing for example.

6 3730 ../mm/page_alloc.c <<rmqueue>>
__mod_zone_freepage_state(zone, -(1 << order),
4 1096 ../mm/page_alloc.c <<__free_one_page>>
__mod_zone_freepage_state(zone, -(1 << order),

> > > I believe it's the case and then the problem goes beyond nohz_full
> > > because if the idle interrupt fired while the tick is stopped and didn't set
> > > TIF_RESCHED, we go back to sleep without calling quiet_vmstat().
> >
> > Yes: e.g. a nohz_full CPU, in idle code, could indeed receive a reschedule
> > IPI; re-enable local IRQs and generic idle code sees the TIF_NEED_RESCHED
> > flag against the idle task. Additionally, the selected task could
> > indirectly released a few pages [to satisfy a low-memory condition] and
> > modify CPU-specific vmstat data i.e. vm_stat_diff[NR_FREE_PAGES].
> >
> >
> > > 2) What if we are running task A in kernel mode while the tick is stopped
> > > (nohz_full). Task A modifies the vmstat and goes to userspace for a long
> > > while.
> > > Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
> > > should really be about dynticks-idle only and not dynticks-full. I've always
> > > been afraid about enforcing that rule though because that would break old
> > > noise-free setups. But perhaps I should...
> >
> > If I understand correctly, I agree. For the latter case, nothing can be
> > done unfortunately since the scheduling-clock tick is stopped.
>
> Hi Frederic,
>
> As far vmstat_updateas I understand, in the context of nohz_full, options are indeed
> limited; albeit, if we can ensure CPU-specific vmstat data is folded on
> return to idle [when required] then this should be good enough.

I suppose the desired behaviour, with the deferred timer for vmstat_sync, is:

"Allow the per-CPU vmstats to be out of sync, but for a maximum of
sysctl_stat_interval".

But Aaron, vmstat_shepherd should be ensuring that per-CPU vmstat_update
work are queued, if the per-CPU vmstat are out of sync.

And:

static void
trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
{
if (!is_timers_nohz_active())
return;

/*
* TODO: This wants some optimizing similar to the code below, but we
* will do that when we switch from push to pull for deferrable timers.
*/
if (timer->flags & TIMER_DEFERRABLE) {
if (tick_nohz_full_cpu(base->cpu))
wake_up_nohz_cpu(base->cpu);
return;
}

* @TIMER_DEFERRABLE: A deferrable timer will work normally when the
* system is busy, but will not cause a CPU to come out of idle just
* to service it; instead, the timer will be serviced when the CPU
* eventually wakes up with a subsequent non-deferrable timer.

You'd want that vmstat_update to execute regardless of whether there are
armed non-deferrable timers.

Should fix both 1 and 2 AFAICS.

2022-02-24 15:26:00

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Thu, Feb 24, 2022 at 09:27:14AM -0300, Marcelo Tosatti wrote:
> On Sat, Feb 19, 2022 at 03:46:16PM +0000, Aaron Tomlin wrote:
> > On Fri 2022-02-18 12:54 +0000, Aaron Tomlin wrote:
> > > On Thu 2022-02-17 17:32 +0100, Frederic Weisbecker wrote:
> > > > > If I understand correctly, in the context of nohz_full, since such work is
> > > > > deferred, it will only be handled in a scenario when the periodic/or
> > > > > scheduling-clock tick is enabled i.e. the timer was reprogrammed on exit
> > > > > from idle.
> > > >
> > > > Oh I see, it's a deferrable delayed work...
> > > > Then I can see two other issues:
> > > >
> > > > 1) Can an interrupt in idle modify the vmstat and thus trigger the need to
> > > > flush it?
>
> Yes. Page allocation and page freeing for example.
>
> 6 3730 ../mm/page_alloc.c <<rmqueue>>
> __mod_zone_freepage_state(zone, -(1 << order),
> 4 1096 ../mm/page_alloc.c <<__free_one_page>
> __mod_zone_freepage_state(zone, -(1 << order),
>
> > > > I believe it's the case and then the problem goes beyond nohz_full
> > > > because if the idle interrupt fired while the tick is stopped and didn't set
> > > > TIF_RESCHED, we go back to sleep without calling quiet_vmstat().
> > >
> > > Yes: e.g. a nohz_full CPU, in idle code, could indeed receive a reschedule
> > > IPI; re-enable local IRQs and generic idle code sees the TIF_NEED_RESCHED
> > > flag against the idle task. Additionally, the selected task could
> > > indirectly released a few pages [to satisfy a low-memory condition] and
> > > modify CPU-specific vmstat data i.e. vm_stat_diff[NR_FREE_PAGES].
> > >
> > >
> > > > 2) What if we are running task A in kernel mode while the tick is stopped
> > > > (nohz_full). Task A modifies the vmstat and goes to userspace for a long
> > > > while.
> > > > Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
> > > > should really be about dynticks-idle only and not dynticks-full. I've always
> > > > been afraid about enforcing that rule though because that would break old
> > > > noise-free setups. But perhaps I should...
> > >
> > > If I understand correctly, I agree. For the latter case, nothing can be
> > > done unfortunately since the scheduling-clock tick is stopped.
> >
> > Hi Frederic,
> >
> > As far vmstat_updateas I understand, in the context of nohz_full, options are indeed
> > limited; albeit, if we can ensure CPU-specific vmstat data is folded on
> > return to idle [when required] then this should be good enough.
>
> I suppose the desired behaviour, with the deferred timer for vmstat_sync, is:
>
> "Allow the per-CPU vmstats to be out of sync, but for a maximum of
> sysctl_stat_interval".
>
> But Aaron, vmstat_shepherd should be ensuring that per-CPU vmstat_update
> work are queued, if the per-CPU vmstat are out of sync.
>
> And:
>
> static void
> trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
> {
> if (!is_timers_nohz_active())
> return;
>
> /*
> * TODO: This wants some optimizing similar to the code below, but we
> * will do that when we switch from push to pull for deferrable timers.
> */
> if (timer->flags & TIMER_DEFERRABLE) {
> if (tick_nohz_full_cpu(base->cpu))
> wake_up_nohz_cpu(base->cpu);
> return;
> }
>
> * @TIMER_DEFERRABLE: A deferrable timer will work normally when the
> * system is busy, but will not cause a CPU to come out of idle just
> * to service it; instead, the timer will be serviced when the CPU
> * eventually wakes up with a subsequent non-deferrable timer.
>
> You'd want that vmstat_update to execute regardless of whether there are
> armed non-deferrable timers.
>
> Should fix both 1 and 2 AFAICS.

Maybe just switching to a non-deferrable timer does not increase the
frequency of vmstat_update calls so much ? It should happen once per
second anyway.

Then the "vmstats out of sync but for a maximum of sysctl_stat_interval"
would be respected, rather than existance of non-deferrable timers.


2022-02-24 16:33:13

by Aaron Tomlin

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Thu 2022-02-24 09:27 -0300, Marcelo Tosatti wrote:
> But Aaron, vmstat_shepherd should be ensuring that per-CPU vmstat_update
> work are queued, if the per-CPU vmstat are out of sync.

Hi Marcelo,

Yes, I agree; albeit, as far as I understand, in the context of a nohz_full
CPU that has its scheduling-clock tick stopped, we cannot rely on any
deferred work.

The purpose of my patch was to prevent a nohz_full CPU from entering idle
state when CPU-specific vmstat data is non-zero.

> And:
>
> static void
> trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
> {
> if (!is_timers_nohz_active())
> return;
>
> /*
> * TODO: This wants some optimizing similar to the code below, but we
> * will do that when we switch from push to pull for deferrable timers.
> */
> if (timer->flags & TIMER_DEFERRABLE) {
> if (tick_nohz_full_cpu(base->cpu))
> wake_up_nohz_cpu(base->cpu);
> return;
> }
>
> * @TIMER_DEFERRABLE: A deferrable timer will work normally when the
> * system is busy, but will not cause a CPU to come out of idle just
> * to service it; instead, the timer will be serviced when the CPU
> * eventually wakes up with a subsequent non-deferrable timer.
>
> You'd want that vmstat_update to execute regardless of whether there are
> armed non-deferrable timers.
>
> Should fix both 1 and 2 AFAICS.
>

If I understand correctly, you are suggesting to switch to a non-deferred
timer for such work when the scheduling-clock tick is stopped? Indeed, it
would address both scenarios yet I'm not sure we'd want that due to the
performance impact which might be more than negligible.


Kind regards,

--
Aaron Tomlin

2022-04-01 11:24:23

by Aaron Tomlin

[permalink] [raw]
Subject: Re: [RFC PATCH] tick/sched: Ensure quiet_vmstat() is called when the idle tick was stopped too

On Thu 2022-02-17 17:32 +0100, Frederic Weisbecker wrote:
> Then I can see two other issues:
>
> 1) Can an interrupt in idle modify the vmstat and thus trigger the need to
> flush it? I believe it's the case and then the problem goes beyond nohz_full
> because if the idle interrupt fired while the tick is stopped and didn't set
> TIF_RESCHED, we go back to sleep without calling quiet_vmstat().
>
> 2) What if we are running task A in kernel mode while the tick is stopped
> (nohz_full). Task A modifies the vmstat and goes to userspace for a long
> while.
>
> Your patch fixes case 1) but not case 2). The problem is that TIMER_DEFERRABLE
> should really be about dynticks-idle only and not dynticks-full. I've always
> been afraid about enforcing that rule though because that would break old
> noise-free setups. But perhaps I should...

Hi Frederic,


Firstly, apologies for the delay.

In reference to case 2:

If I understand correctly, even if TIMER_DEFERRABLE is removed
refresh_cpu_vm_stats() cannot be invoked since the scheduling-clock tick is
disabled i.e. non-deferrable timers are serviced by the tick, no?
So, the only option would be to interrupt the workload - not desirable - or
detect any remaining differentials prior to entering userspace?


Kind regards,

--
Aaron Tomlin