Re: [PATCH v1] cpuidle: governors: menu: Predict longer idle time when in doubt

Rafael J. Wysocki
2025-10-17T09:39:21Z

On Fri, Oct 17, 2025 at 10:22 AM Christian Loehle
<christian.loehle@arm.com> wrote:
>
> On 10/16/25 17:25, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > It is reported that commit 85975daeaa4d ("cpuidle: menu: Avoid discarding
> > useful information") led to a performance regression on Intel Jasper Lake
> > systems because it reduced the time spent by CPUs in idle state C7 which
> > is correlated to the maximum frequency the CPUs can get to because of an
> > average running power limit [1].
> >
> > Before that commit, get_typical_interval() would have returned UINT_MAX
> > whenever it had been unable to make a high-confidence prediction which
> > had led to selecting the deepest available idle state too often and
> > both power and performance had been inadequate as a result of that in
> > some cases. This was not a problem on systems with relatively
> > aggressive average running power limits, like the Jasper Lake systems
> > in question, because on those systems it was compensated by the ability
> > to run CPUs at relatively higher frequencies.
> >
> > Commit 85975daeaa4d addressed that by causing get_typical_interval() to
> > return a number based on the recent idle duration information available
> > to it in those cases, but that number is usually smaller than the
> > maximum idle duration observed recently which may be regarded as an
> > overly optimistic choice.
> >
> > Namely, it may be argued that when the samples considered by
> > get_typical_interval() are spread too much for a high-confidence
> > prediction to be made, the function should fall back to returning a
> > number that is likely to be an upper bound for the duration of the
> > upcoming idle interval and that number needs to be at least equal to
> > the maximum recently observed idle time. Otherwise, the governor may
> > miss an oportunity to reduce power without hurting performance in a

Ah, a typo.

> > noticeable way. Of course, it may also be argued the other way around,
> > but the available data indicate that get_typical_interval() should
> > rather tend to return larger numbers as that causes the governor to
> > behave more closely to its past behavior from before the problematic
> > commit.
> >
> > Accordingly, modify get_typical_interval() to return the maximum
> > recently observed idle time when it is unable to make a high-
> > confidence prediction.
> >
> > Fixes: 85975daeaa4d ("cpuidle: menu: Avoid discarding useful information")
> > Closes: https://lore.kernel.org/linux-pm/36iykr223vmcfsoysexug6s274nq2oimcu55ybn6ww4il3g3cv@cohflgdbpnq7/ [1]
> > Reported-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> > Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> > Cc: All applicable <stable@vger.kernel.org>
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> > drivers/cpuidle/governors/menu.c | 6 +++++-
> > 1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > --- a/drivers/cpuidle/governors/menu.c
> > +++ b/drivers/cpuidle/governors/menu.c
> > @@ -116,6 +116,7 @@ static void menu_update(struct cpuidle_d
> > static unsigned int get_typical_interval(struct menu_device *data)
> > {
> > s64 value, min_thresh = -1, max_thresh = UINT_MAX;
> > + unsigned int max_overall = 0;
>
> nit: for reverse xmas this should be one further down?

Actually, I can combine this with the min and max definition.

> Maybe s/max_overall/max_first_pass/?

I can call it grand_max.

> > unsigned int max, min, divisor;
> > u64 avg, variance, avg_sq;
> > int i;
> > @@ -151,6 +152,9 @@ again:
> > if (!max)
> > return UINT_MAX;
> >
>
> Or alternatively a comment:
> /* Save the max before we discard any intervals */
> or something.
>
> > + if (max_overall < max)
> > + max_overall = max;
> > +> if (divisor == INTERVALS) {
> > avg >>= INTERVAL_SHIFT;
> > variance >>= INTERVAL_SHIFT;
> > @@ -198,7 +202,7 @@ again:
> > * maximum, so return the latter in that case.
> > */
> > if (divisor >= INTERVALS / 2)
> > - return max;
> > + return max_overall;
> >
> > return UINT_MAX;
> > }
> >
>
> Anyway, the patch makes sense, let me run some tests and get back.

Thanks!