On 2026/9/18 20:06, Rafael J. Wysocki (Intel) wrote:
> On Fri, Sep 18, 2026 at 4:09 AM Yaxiong Tian <[email protected]> wrote:
>>
>> On 2026/9/18 03:34, Rafael J. Wysocki (Intel) wrote:
>>> On Wed, Jul 29, 2026 at 8:16 AM Yaxiong Tian <[email protected]> wrote:
>>>> cpuidle_governor_latency_req() is evaluated on every idle-state
>>>> selection. It aggregates the per-CPU resume latency with the global
>>>> CPU latency and wakeup latency QoS limits
>>> True.
>>>
>>>> by repeatedly calling
>>>> get_cpu_device() and pm_qos_read_value() cpu_latency_qos_limit()
>>>> cpu_wakeup_latency_qos_limit().
>>> I would say "every time" rather than "repeatedly", but fair enough.
>>>
>>> However, those functions don't do anything expensive except for
>>> defensive checks that can be omitted. Have you tried to omit them?
>> I haven't tried that, but I found that function_graph may introduce
>> measurement errors, especially for very short functions.
>>>> Use ftrace's function_graph, we can see:
>>>> parent: do_idle
>>>> parent_total_ns: 36671010505
>>>> parent_count: 5994
>>>>
>>>> SYMBOL TIME_NS
>>>> %ROOT %PARENT COUNT
>>>> --------------------------------------------------------------------------------------------------
>>>> do_idle 36671010505
>>>> 100.00% 100.00% 5994
>>>> cpuidle_idle_call 35566528731
>>>> 96.99% 96.99% 8570
>>>> call_cpuidle 35476606844
>>>> 96.74% 99.75% 8561
>>>> cpuidle_enter 35472932468
>>>> 96.73% 99.99% 8526
>>>> cpuidle_select 52097031
>>>> 0.14% 0.15% 8580
>>>> menu_select 49555181
>>>> 0.14% 95.12% 8580
>>>> tick_nohz_get_sleep_length 28843887
>>>> 0.08% 58.21% 8570
>>>> cpuidle_governor_latency_req 9567488
>>>> 0.03% 19.31% 8580
>>>> tick_nohz_tick_stopped 2057031
>>>> 0.01% 4.15% 15695
>>>> cpuidle_reflect 11427201
>>>> 0.03% 0.03% 8561
>>>> menu_reflect 6579506
>>>> 0.02% 57.58% 8526
>>>> tick_nohz_idle_got_tick 2231559
>>>> 0.01% 33.92% 8526
>>>> __sysvec_apic_timer_interrupt 105520
>>>> 0.00% 0.92% 3
>>>> tick_nohz_idle_stop_tick 8279641
>>>> 0.02% 0.02% 1475
>>>> ---- skip
>>>>
>>>> The majority of the time spent in cpuidle_enter for CPUs entering
>>>> idle state has already been charged to the idle path. Among the
>>>> remaining contributors, cpuidle_governor_latency_req() accounts
>>>> for a non-negligible portion of the overall latency.
>>>>
>>>> Under the menu governor this shows up hot: ftrace data shows,
>>>> cpuidle_governor_latency_req() accounts for about 19.9% of
>>>> menu_select() time (~1.9 us/call). After caching the aggregated
>>>> value per CPU and invalidating via QoS notifiers, that share drops to
>>>> about 4.2% (~0.3 us/call), roughly a 6x reduction on this path.
>>> Is there any real-world workload in which that difference is actually
>>> visible?
>> Sorry, I only tested it under no load.
>>
>>>> The ftrace data before and after the optimization is shown below:
>>>> 1) original
>>>> parent: menu_select
>>>> parent_total_ns: 160492937
>>>> parent_count: 16718
>>>>
>>>> SYMBOL TIME_NS
>>>> %ROOT %PARENT COUNT
>>>> --------------------------------------------------------------------------------------------------
>>>> menu_select 160492937
>>>> 100.00% 100.00% 16718
>>> Where did you lose menu_update()?
>> Because menu_update() was optimized away by the compiler, it can't be seen
>> in /proc/kallsyms, so it won't be traced by ftrace either.
> How could it be optimized away?
Sorry, "optimized away" was a poor choice of words. Nothing was removed
- menu_update() still runs, but the compiler inlined it into its only
caller, so no out-of-line body is emitted. No body -> no function entry
-> no call fentry site in __mcount_loc -> no kallsyms symbol -> nothing
for function_graph to trace. GCC can do that because menu_update() is
static, has exactly one caller (menu.c:228) .