Hi Juri,

On Mon, Jul 10, 2017 at 3:55 AM, Juri Lelli <juri.le...@arm.com> wrote:
> Hi Joel,
>
> On 09/07/17 10:08, Joel Fernandes wrote:
>> Currently the iowait_boost feature in schedutil makes the frequency go to 
>> max.
>> This feature was added to handle a case that Peter described where the
>> throughput of operations involving continuous I/O requests [1] is reduced due
>> to running at a lower frequency, however the lower throughput itself causes
>> utilization to be low and hence causing frequency to be low hence its 
>> "stuck".
>>
>> Instead of going to max, its also possible to achieve the same effect by
>> ramping up to max if there are repeated in_iowait wakeups happening. This 
>> patch
>> is an attempt to do that. We start from a lower frequency (iowait_boost_min)
>> and double the boost for every consecutive iowait update until we reach the
>> maximum iowait boost frequency (iowait_boost_max).
>>
>> I ran a synthetic test on an x86 machine with intel_pstate in passive mode
>> using schedutil. The patch achieves the desired effect as the existing
>> behavior. Also tested on ARM64 platform and see that there the transient 
>> iowait
>> requests aren't causing frequency spikes.
>>
>> [1] https://patchwork.kernel.org/patch/9735885/
>>
>> Cc: Srinivas Pandruvada <srinivas.pandruv...@linux.intel.com>
>> Cc: Len Brown <l...@kernel.org>
>> Cc: Rafael J. Wysocki <r...@rjwysocki.net>
>> Cc: Viresh Kumar <viresh.ku...@linaro.org>
>> Cc: Ingo Molnar <mi...@redhat.com>
>> Cc: Peter Zijlstra <pet...@infradead.org>
>> Suggested-by: Peter Zijlstra <pet...@infradead.org>
>> Signed-off-by: Joel Fernandes <joe...@google.com>
[..]
>>
>> diff --git a/kernel/sched/cpufreq_schedutil.c 
>> b/kernel/sched/cpufreq_schedutil.c
>> index 622eed1b7658..4d9e8b96bed1 100644
>> --- a/kernel/sched/cpufreq_schedutil.c
>> +++ b/kernel/sched/cpufreq_schedutil.c
>> @@ -53,7 +53,9 @@ struct sugov_cpu {
>>       struct update_util_data update_util;
>>       struct sugov_policy *sg_policy;
>>
>> +     bool prev_iowait_boost;
>>       unsigned long iowait_boost;
>> +     unsigned long iowait_boost_min;
>>       unsigned long iowait_boost_max;
>>       u64 last_update;
>>
>> @@ -168,22 +170,47 @@ static void sugov_get_util(unsigned long *util, 
>> unsigned long *max)
>>       *max = cfs_max;
>>  }
>>
>> +static void sugov_decay_iowait_boost(struct sugov_cpu *sg_cpu)
>> +{
>> +     sg_cpu->iowait_boost >>= 1;
>> +
>> +     if (sg_cpu->iowait_boost < sg_cpu->iowait_boost_min)
>> +             sg_cpu->iowait_boost = 0;
>> +}
>> +
>>  static void sugov_set_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
>>                                  unsigned int flags)
>>  {
>>       if (flags & SCHED_CPUFREQ_IOWAIT) {
>> -             sg_cpu->iowait_boost = sg_cpu->iowait_boost_max;
>> +             /* Remember for next time that we did an iowait boost */
>> +             sg_cpu->prev_iowait_boost = true;
>> +             if (sg_cpu->iowait_boost) {
>> +                     sg_cpu->iowait_boost <<= 1;
>> +                     sg_cpu->iowait_boost = min(sg_cpu->iowait_boost,
>> +                                                sg_cpu->iowait_boost_max);
>> +             } else {
>> +                     sg_cpu->iowait_boost = sg_cpu->iowait_boost_min;
>> +             }
>>       } else if (sg_cpu->iowait_boost) {
>>               s64 delta_ns = time - sg_cpu->last_update;
>>
>>               /* Clear iowait_boost if the CPU apprears to have been idle. */
>>               if (delta_ns > TICK_NSEC)
>>                       sg_cpu->iowait_boost = 0;
>
> In this case we might just also want to reset prev_iowait_boost
> unconditionally and return.

Ok, will do.

>> +
>> +             /*
>> +              * Since we don't decay iowait_boost when its consumed during
>> +              * the previous SCHED_CPUFREQ_IOWAIT update, decay it now.
>> +              */
>
> Code below seems pretty self-explaning to me. :)
>

Ok :)

>> +             if (sg_cpu->prev_iowait_boost) {
>> +                     sugov_decay_iowait_boost(sg_cpu);
>> +                     sg_cpu->prev_iowait_boost = false;
>> +             }
>>       }
>>  }
>>
>>  static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, unsigned long 
>> *util,
>> -                            unsigned long *max)
>> +                            unsigned long *max, unsigned int flags)
>>  {
>>       unsigned long boost_util = sg_cpu->iowait_boost;
>>       unsigned long boost_max = sg_cpu->iowait_boost_max;
>> @@ -195,7 +222,16 @@ static void sugov_iowait_boost(struct sugov_cpu 
>> *sg_cpu, unsigned long *util,
>>               *util = boost_util;
>>               *max = boost_max;
>>       }
>> -     sg_cpu->iowait_boost >>= 1;
>> +
>> +     /*
>> +      * Incase iowait boost just happened on this CPU, don't reduce it right
>> +      * away since then the iowait boost will never increase on subsequent
>> +      * in_iowait wakeups.
>> +      */
>> +     if (flags & SCHED_CPUFREQ_IOWAIT && this_cpu_ptr(&sugov_cpu) == sg_cpu)
>> +             return;
>> +
>> +     sugov_decay_iowait_boost(sg_cpu);
>
> Mmm, do we need to decay even when we are computing frequency requests
> for a domain?
>
> Considering it a per-cpu thing, isn't enough that it gets bumped up or
> decayed only when a CPU does an update (by using the above from
> sugov_update_shared)?
>
> If we go this way I think we will only need to reset prev_iowait_boost
> if delta_ns > TICK_NSEC during the for_each_cpu() loop of sugov_next_
> freq_shared().
>

Actually the "decay" was already being done before (without this
patch), I am just preserving the same old behavior where we do decay.
Perhaps your proposal can be a separate match? Or did I miss something
else subtle here?

Thanks,

-Joel

Reply via email to