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) .

Reply via email to