[Google Pixel XL ROMs, Kernels, Recoveries, & Other] Freak07:
Info Post

So this post will be dedicated to information about EAS in general.

Another amazing write up about alucardsched by a talented new dev [MENTION=6745491]joshuous[/MENTION]:

This is what I understand from tracing the Alucardsched code. I apologise if my understanding is incorrect.

Firstly, next frequency selection with Schedutil (very simple):

Code:

next_freq = 1.25 * Max_freq * current_util / max_util;

Now, here's a quick overview of one cycle of frequency selection in Alucardsched:

1. You have two key extra tunables: PUMP_INC_STEP and PUMP_DEC_STEP

2. Current utilisation here refers to the system's current demand. It is calculated using:

Code:

curr_util = (util * (100 + tunables->boost_perc)) / max_utilisation

The "util" is a value determined by the EAS scheduler.

3. Target load here refers to what processor is currently supplying. It is calculated using:

Code:

target_load = (current_freq * 100) / max_freq;

4. The key idea is to ensure that supply satisfies demand. That is, target load ≈ current load.

5. If target_load <= current_load (too little supply), then we want to increase frequencies to match the system’s load. For Alucardsched, frequency is increased by jumping up PUMP_INC_STEP number of steps in the OPP table. (By OPP table, I refer to the available frequencies that you can switch to)

6. If target_load > current_load (too much supply), then we want to decrease frequencies to match the system’s load. For Alucardsched, frequency is decreased by jumping down PUMP_DEC_STEP number of steps in the OPP table.

7. Do note that Alucardsched jumps several frequency steps, compared to Schedutil and Interactive which try to jump immediately to a calculated next frequency. In this way, Alucardsched doesn't care about the specific value of the next speed. It's like driving a car, and deciding to increase gears by several steps instead of deciding to jump immediately to a specific gear.

Extra Tunables

FREQ_RESPONSIVENESS

PUMP_INC_STEP_AT_MIN_FREQ

PUMP_DEC_STEP_AT_MIN_FREQ

Sometimes you want the "pumping" behaviour to behave differently at lower and higher frequencies. FREQ_RESPONSIVENESS can be seen as the mark that divides the low and high frequencies. If the current frequency is less than FREQ_RESPONSIVENESS, the number of frequency skips will be PUMP_INC_STEP_AT_MIN_FREQ and PUMP_DEC_STEP_AT_MIN_FREQ instead of the usual PUMP_INC_STEP and PUMP_DEC_STEP.

How is it used? If your frequency is low (lower than FREQ_RESPONSIVENESS) and your system demand is high, you ideally want to boost frequency speeds quickly. This is when PUMP_INC_STEP_AT_MIN_FREQ kicks in. PUMP_INC_STEP_AT_MIN_FREQ is usually (and should be) a larger value than PUMP_INC_STEP. When your frequency is high (higher than FREQ_RESPONSIVENESS) and your system demand is high, you don't want to be jumping so many steps up otherwise you will hit max frequencies too quickly (overkill). I'm pretty sure you can figure out how PUMP_DEC_STEP and PUMP_DEC_STEP_AT_MIN_FREQ works after having read this paragraph

Tldr;

Schedutil: simpler

Alucardsched: more tunable

Code:

IF CURRENT_FREQ < FREQ_RESPONSIVENESS:

PUMP_INC_STEP_AT_MIN_FREQ and PUMP_DEC_STEP_AT_MIN_FREQ are used

ELSE:

PUMP_INC_STEP and PUMP_DEC_STEP are used

PUMP_INC_STEP_AT_MIN_FREQ should be larger than PUMP_INC_STEP.

Note: There is however a potential problem (if you may call it one) with Alucardsched: just like Interactive you rely almost entirely on heuristics (trial and error) to control your frequency jumps instead of letting the system choose it for you, like in Schedutil. In that way, Alucardsched detracts from the goal of Schedutil to provide a simple frequency choosing mechanism. Without the proper tuning to meet your specific usage, it is likely that your frequencies will overshoot or undershoot past the needed load on Alucardsched (just like in Interactive). I would recommend that you play with the tunables to see what works best for you.

Here is information about energy-dcfc (Dynamic Capacity and Frequency Capping):

This new governor is based on schedutil. It uses target_load variables as thresholds to let the governor decide when to cap the frequencies for both clusters. These variables are called "load1_cap" and "load2_cap". Load1_cap corresponds to target_load1 meaning anything that is below target_load1, it caps using load1_cap. Anything above target_load1 and below target_load2, use load2_cap. Anything above target_load 2 and the maximum frequency will be used.

As a result of this behaviour, bit shift value must be set to 1. Anything higher than 1 and frequency scaling will be extremely slow. This is because the lower the maximum frequency, the lower the next frequency target is because the frequency range is being limited.

AS OF V009: The governor has now incorporated [MENTION=5736502]Kyuubi10[/MENTION] 's schedutil dynamic formula change. When load is below target_load1 it will use add bitshift in the formula. If load is above target_load1 but below target_load2, it won't use any bit shifting at all. If load is more than target_load2, it will subtract bitshift in the formula. This has proven to be very efficient with a touchboost-like behaviour when scrolling (Up to the capped frequency of this governor), then steady performance in between, and on heavy workloads it will not just stay on maximum frequency, in fact it will hover around 1.3-1.9GHz to ensure thermals are good as well as battery endurance.

This governor is aimed with maximum efficiency in mind. Do not expect outstanding performance with this governor.

helix_schedutil explained by [MENTION=5736502]Kyuubi10[/MENTION]

To understand Helix_schedutil you must first understand the original schedutil algorithm.

Here it is:

next_freq = maxfreq + (maxfreq >> bitshift) * util/maxcapacity

Explanation:

The most obvious difference of this algorithm is that it moves away from the idea of scaling frequencies up or down which were used in previous generations of governors.

Instead the aim of the above algorithm is to calculate the most appropriate frequency for the TOTAL CPU load.

NOTE: This is TOTAL load on CPU, not just load for the current frequency step as Interactive used to calculate with.

Now, for you numberphiles like myself that like understanding algorithms... Let's break it down:

"util/maxcapacity = Load."

The above creates a percentage value in decimal format (80% = 0.8) which represents the TOTAL load on CPU.

the algorithm now reads the following way:

next_freq = maxfreq + (maxfreq >> bitshift) * load

"maxfreq + (maxfreq >> bitshift)"

Essentially the aim of the above is to ensure that next_freq is always a little higher than the exact value needed to cover the load.

Bitshift: (paraphrasing [MENTION=4388232]ZeroInfinity[/MENTION]) in programming the ">>" mathematical function allows for shifting the binary values towards the direction of the arrows by "N" times.

In this case it is towards the right.

The relationship between "N" and the calculation in the "()" is as follows:

Bitshift = 1 = maxfreq/2

Bitshift = 2 = maxfreq/4

Bitshift = 3 = maxfreq/8

If the "+()" didn't exist in the algorithm, the chosen frequency would be exactly enough to cover the load.

If load is 0.6, aka 60%, all you need is a frequency = 60% of max frequency.

This would be bad since it doesn't leave any capacity/bandwidth leftover for inevitable bumps in load, nor space for EAS itself to run. Thus inevitably creating lags.

To keep a bit of free bandwidth you add "(maxfreq >> bitshift)".

Finally the problem I encountered, if bitshift = 2, then the result of the algorithm is that any load above 0.8 will result in a next_freq HIGHER than maxfreq. - This is your tipping point. As any load higher than 80% will wake up a new CPU.

Which means you have still about 20% of the CPU's max capacity being unused. Such a CPU is only 80% efficient.

Therefore by increasing bitshift to 3, the algorithm reads:

"maxfreq+(maxfreq/8)*load = next_freq"

This way you can use 89% of capacity before reaching max frequency of the CPU.

With bitshift=4 it reads:

"maxfreq+(maxfreq/16)*load = next_freq"

This allows you to use up to 94% total CPU load before reaching max frequency.

While this is great for improving efficiency at the higher frequencies, it doesn't leave enough bandwidth when calculating lower frequencies, and creates lag when load spikes at lower frequencies.

Update to the explanation:

After being inspired by the concept of [MENTION=4388232]ZeroInfinity[/MENTION]'s new governor - Energy-DCFC, I decided to carry out a couple of tests on HTC 10 using variations of Helix_Schedutil.

The focus was stress-testing by increasing the current frequency load above 100%. (AKA Use up all of the bandwidth of the current frequency step.)

After the testing me and Zero worked on this new version of Helix_Schedutil.

The current behaviour of the governor is the following:

- Boost frequencies when load is below Target_Load1. (Boost can be increased by DECREASING bit_shift1 value.)

- Between Target_Loads there is no bit_shift at all. The governor just uses the following algorithm instead - (max_freq*util/max = next_freq)

- Loads higher than Target_Load2 will be THROTTLED. Bit_Shift2 here is subtracted rather than added. (Throttle effect can be increased by DECREASING bit_shift2 value.)

The result is that low freqs have spare bandwidth to avoid lags, middle frequencies leave no extra bandwidth at all, while higher frequencies are throttled to save battery.

Another focus of the governor update is to reduce overhead as much as possible. This results in a very responsive governor which isn't overly demanding on battery life.

Schedtune.boost values recommended for use with this governor:

Top_App: 5

Foreground: -50

Background: -50

Global: -50

Energy-DCFC is still recommended for those who prefer battery life over performance, but if you prefer greater performance then this governor can be used without making you feel guilty about wasting battery.

correction a misconception:

Some people describe tipping point as the load threshold which the governor uses to decide whether to ramp up or down.

While if you look into the behaviour of the governor it may appear that it behaves in such a way, it is technically incorrect.

As I mentioned previously this new algorithm moves away from the behaviour of legacy governor algorithms which focus on the current frequency load.

This governor does no ramping up or down.

It isn't even aware of the current frequency load, as it only knows the load relative to max capacity.

The misconception appears based on a property of the algorithm that results in a consistent load at any chosen frequency. This is a coincidental result of the algorithm, even though the algorithm is completely unaware of it.

Tipping point is in fact the load percentage at which the CPU reaches max frequency and any increase in load forces it to wake up a new core

here is some Information about pwrutil governor:

This new governor is based on schedutil.

A much simpler yet very effective governor based on schedutil. All this changes is the calculation to get the next frequency. Rather than using bit shift to calculate tipping point and what not, we don't use it at all. This is much much more efficient if you use my program called "schedutilCalculator" to calculate what the next frequency is. For example, a load of 25% with a max freq of 2150400 will get 500MHz as next frequency. A load of 50% will get 1GHz as next frequency. A load of 75% will get 1.5-1.6GHz as next frequency. A load of 100% will get 2.15GHz as next frequency. You can see the lower the load, the much lower the frequency selection will be, but the higher the load and the higher the frequency selection is. So it can go from a very low powered state with 50% load and under, to a high performance state from 75% load and above.

Includes a tunable called "utilboost" which is basically a load multiplier - it makes load higher than it is perceived by the governor, thus making next frequency selection higher. Remember utilisation does not equal load. The equation of calculating load is util / max capacity of a CPU (which should be 1024). So 512 / 1024 = 0.5 (50% load).

UTIL BOOST IS NOT MEANT TO BE USED WITH SCHEDTUNE.BOOST AT THE SAME TIME! EITHER USE ONE OR THE OTHER OR ELSE PERFORMANCE WILL BE OVERKILL AND BATTERY LIFE WILL DRAIN MUCH FASTER!!!

Util boost is supposed to be a replacement of schedtune.boost. schedtune.boost applies boosting to both clusters, whereas util boost allows boosting per-cluster so users can have much more control.