[Galaxy S II General] droidphile:
New Governor(s)

Pegasusq Governor

Let's see what is pegasusq governor from Samsung which claims to be a multi core aware governor.

Some Basics to Remember Before Reading On:

Some patience is required to understand a governor.

Pegasusq is basically an ondemand based governor which also controls hotplugging.

Run Queue: We know mutiple processes can run at once on our device. These active processes are placed in an array called a run queue along with their priority values. (Priority is used by the task scheduler to determine which process is to run next) To ensure each process has a fair share of resources, each one is run for some time period then paused and placed back into the run queue. When a program is stopped to let another run - the program with the highest priority in the run queue is then allowed to execute.

Talking w.r.t to Android O.S and GS2 CPU, each core is given a run queue, which maintains both an active and expired array of processes. The scheduler selects the next process from the active array with highest priority. When a process' time period expires, it is placed into the expired array with some priority. When the active array contains no more processes, the scheduler swaps the active and expired arrays.

Wall Time is the total up time of CPU. Idle Time is the total idle time of the CPU. The difference (wall time minus idle time) gives CPU Busy Time. Load on CPU is calculated as percentage of Busy Time on Up Time. (Doesn't it make a lot of sense). Now you know exactly how is load measured.

Governor doesn't scale CPU but tells the CPU driver to do so.

Sampling means to evaluate load.

Smooth scaling is also done by CPU driver, not by governor.

Switching to pegasusq will deactivate Stand Hotplug since we don't need two logics to do the same thing at the same time and create conflicts.

Switching to a different governor from Stand hotplug will re-activate Stand Hotplug since we need a logic to control hotplugging.

Use scripts or SetCpu to change governor tunables.

Gokhanmoral modified pegasusq (originally authored by Samsung for quad core devices) in Siyah kernel to be dual core friendly.

Parameters:-

1) sampling_rate - Measured in uS and actual meaning being Sampling Interval, this factor determines how often the governor should poll for CPU usage in terms of frequency and load percentage to make scaling decisions - either scale CPU Up or scale it Down.

UNIT: Miscroseconds

2) up_threshold - Measured as percentage, when load on CPU is equal to above up threshold, CPU is scaled Up. Lower value - early scale up, and vice-verse.

UNIT: Percentage

3) sampling_down_factor - Acts as a multiplier for sampling interval for re-evaluating the load when CPU is truly busy and is on highest clock frequency (policy max). Setting to 1 makes no difference and causes CPU to immediately scale down from highest frequency. Sampling down factor is NOT valid for lower frequencies and low load conditions. Note that CPU is scaled up to max frequency when max_load_freq is greater than up_threshold*current frequency. (or to cur_freq + (freq_step * policy.max_freq) whichever is smaller) Max_load_freq is an arbitrary frequency calculated as the maximum of load_frequencies. Load_frequency is an arbitrary frequency which describes the frequency the device theoretically needs to handle 100% load, calculated as load*average_frequency.

To sum up, use non-zero sampling_down_factor to avoid governor jumping down to lower frequency even on high CPU load.

UNIT: Positive Integer

4) down_differential - After spending sampling_down_factor*sampling_rate micro seconds at maximum frequency on high load, governor samples the load again to calculate an approx target frequency to scale-down-to which should not trigger up_threshold in the next sample. (Triggering up threshold may cause jumping to max frequency again). Max_load_freq is checked against (up_threshold - down_differential) * current frequency. If found to be smaller, CPU is scaled down to a target frequency as described above. Down_differential also act as the factor to prevent aggressive scale down.

Higher value of down_differential corresponds to delayed scaling down.

UNIT: Positive Integer

5) freq_step - Defines how much as a percentage of maximum frequency, governor should increase CPU frequency each time CPU load reaches up_threshold.

UNIT: Percentage

6) cpu_up_rate - No of samples to evaluate load to scale CPU Up. After cpu_up_rate samples are finished for a frequency, CPU scale-Up logic is executed. In other words - before scaling Up, cpu_up_rate*sampling_rate micro seconds are spend at a frequency.

UNIT: Positive Integer

7) cpu_down_rate - No of samples to evaluate load to scale CPU Down. After CPU_down_rate samples are finished for a frequency, CPU scale-Down logic is executed. In other words - before scaling Down, cpu_down_rate*sampling_rate micro seconds are spend at a frequency.

UNIT: Positive Integer

8) hotplug_freq_1_1 - Up threshold frequency to turn second core On, when some other conditions is also met. ie If (minimum frequency greater than or equal to hotplug_freq 1 1 and run queue length is greater than hotplug_rq_1_1) Hotplug IN Second Core. Higher value correpsonds to delay in turning on second core.

UNIT: Kilo Hertz

9) hotplug_freq_2_0 - Down threshold frequency to turn second core Off, when some other conditions is also met. ie If (maximum frequency less than hotplug_freq 2 0 and run queue length is less than or equal to hotplug_rq_2_0) Hotplug OUT Second Core. Lower value correpsonds to delay in turning off second core.

UNIT: Kilo Hertz

10) hotplug_rq_1_1 - Threshold run queue length for second core to turn on.

UNIT: Positive Integer

11) hotplug_rq_2_0 - Threshold run queue length for second core to turn off.

UNIT: Positive Integer

12) freq_for_responsiveness - Until freq_for_responsiveness, Up Threshold considered for sampling load is up_threshold_at_min_freq. Also during the part where CPU is at maximum load frequency, governor need to find the optimal frequency as the next frequency - which should not trigger up_threshold in the next sampling. When such a frequency_next is found to be a) less than freq_for_responsiveness b) will not trigger down_threshold in the next sample, then the optimal frequency is set to freq_for_responsiveness.

13) up_threshold_at_min_freq - This threshold is used as up threshold while sampling at frequencies less than freq_for_responsiveness. Above that, normal up_threshold is used. This gives us an option to make scaling aggressive/relaxed until a frequency and normal for higher frequencies. Again, during calculation of optimal frequency which should not trigger up policy, down threshold to consider is difference between up_threshold_at_min_freq and down_differential

14) ignore_nice_load - Setting to 1 causes governor to ignore load resulted by nice processes while making scaling decisions. Nice processes are the one i/o scheduler refers to as low priority process.

UNIT: Boolean 1 or 0

15) io_is_busy - Setting to 1 causes treating i/o wait time as CPU busy time. I/O busy is just an indication that CPU is performance critical, and system is not actually idle. IO wait time is excluded from the CPU idle time value is 1.

UNIT: Boolean 1 or 0

16) max_cpu_lock - If set to zero, hotplugs in and out second core when appropriate. Otherwise specifies no of cores to be considered for hotplugging. Leave it as default 0.

UNIT: Integer 0/1/2

17) hotplug_lock - Hotplugging second core is cancelled if it's value is greater than zero. The value should be greater than value of max_cpu_lock for a non-zero value. Leave it as 0.

UNIT: Integer 0/1/2

18) *cpu_up_freq - Calculated as minimum of (its current value and maximum frequency), this tunable is actually not used by the governor.

UNIT: Kilo Hertz

19) *cpu_down_freq - Calculated as maximum of ( its current value and minimum frequency), this tunable is actually not used by the governor.

UNIT: Kilo Hertz

20) *up_nr_cpus - Calculated as minimum of (its current value and num of possible cpus), this tunable is used by the governor to indirectly make Hotplugging decisions, but may not be useful for a 2 core CPU.

UNIT: Integer 1/2

21) dvfs_debug - Set to 1 to enable governor logging. If you're an enthusiast, this may be useful to view the impact of the values for governor tunable set by inspecting the log.

UNIT: Boolean 1 or 0

* - Parameters removed in siyah kernel since they're not actually used in the governor code.

Sample Tweaks:-

Assuming - i) You have 18 steps freq table ii) Scaling min is not greater than 200 mhziii) Scaling max is not less than 1000 mhz

Aggressive

echo "75" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold
echo "65" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold_at_min_freq
echo "40000" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_rate
echo "2" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_down_factor
echo "10" > /sys/devices/system/cpu/cpufreq/pegasusq/down_differential
echo "60" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_step
echo "400000" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_for_responsiveness
echo "10" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_up_rate
echo "20" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_down_rate
echo "400000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_1_1
echo "300000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_2_0
echo "200" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_1_1
echo "150" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_2_0
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/ignore_nice_load
echo "1" > /sys/devices/system/cpu/cpufreq/pegasusq/io_is_busy
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/max_cpu_lock
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_lock

Relaxed

echo "90" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold
echo "80" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold_at_min_freq
echo "60000" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_rate
echo "1" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_down_factor
echo "5" > /sys/devices/system/cpu/cpufreq/pegasusq/down_differential
echo "20" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_step
echo "300000" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_for_responsiveness
echo "15" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_up_rate
echo "15" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_down_rate
echo "500000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_1_1
echo "300000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_2_0
echo "350" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_1_1
echo "200" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_2_0
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/ignore_nice_load
echo "1" > /sys/devices/system/cpu/cpufreq/pegasusq/io_is_busy
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/max_cpu_lock
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_lock

My Settings: I don't want unnecessary power drain, and don't want lag to save extra juice. Scaling from 200 to 1200 with every frequency that's multiple of 100 in the table.

echo "80" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold
echo "40" > /sys/devices/system/cpu/cpufreq/pegasusq/up_threshold_at_min_freq
echo "40000" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_rate
echo "2" > /sys/devices/system/cpu/cpufreq/pegasusq/sampling_down_factor
echo "5" > /sys/devices/system/cpu/cpufreq/pegasusq/down_differential
echo "40" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_step
echo "200000" > /sys/devices/system/cpu/cpufreq/pegasusq/freq_for_responsiveness
echo "10" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_up_rate
echo "20" > /sys/devices/system/cpu/cpufreq/pegasusq/cpu_down_rate
echo "400000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_1_1
echo "300000" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_freq_2_0
echo "300" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_1_1
echo "200" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_rq_2_0
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/ignore_nice_load
echo "1" > /sys/devices/system/cpu/cpufreq/pegasusq/io_is_busy
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/max_cpu_lock
echo "0" > /sys/devices/system/cpu/cpufreq/pegasusq/hotplug_lock

Once again, note that stand hotplug is disabled when pegasusq is active. After setting your values, just make sure you didn't configure pegasusq wrong where only one core is on all the time or both cores are online all the time. Open tegrak second core app and make sure second core turns on when needed and turns off when done.

Points to Note While Tweaking Pegasusq:-

1) Actual sampling interval is not the value of sampling_rate since load is evaluated after cpu_up_rate number-of-samples while scaling up and cpu_down_rate times number of samples while scaling down. So don't go for big values for sampling_rate. You're not saving battery but causing lags.

2) Always make sure that directly related parameters are rightly configured. For example a sampling_rate of 50000, cpu_up_rate of 10, cpu_down_rate of 20 means load is sampled after 10*50000=1000000=1 second for scale up and 20*50000=2 seconds for scale down.

3) Let value of down_differential always be between 5 and 10. Atleast 5 and 15. The difference between upthreshold and down_differential is considered as the percentage against current frequency to find a frequency to scale down to when CPU was on max_load_frequency. (This max_load_frequency is not your scaling_max_frequency. It's an arbitrary freq which is something smaller than that)

4) We know frequency jumps straight to max a little too often with ondemand based governors. One situation where this could happen is when max_load_freq is found to be greater than up_threshold percentage of current frequency. (If current frequency + (freq_step * policy.max_freq) is smaller than max frequency, it will jump to this frequency instead). So it's better not to go with very low up_threshold.

5) sampling down factor is the number of samples to spend at highest CPU frequency before re-evaluating the load. Setting to 1 may be battery friendly but also causes scale down even if CPU was very busy. A trade-off value is 2. High sampling_down_factor is not recommended. We don't need CPU to stay at highest freq forever.

6) Setting freq_step = 100% voids the reason for it to exist. Let it be something between 20% and 50% / 60% depending on your need. Note that smooth_scaling and freq_step does the same thing. Use only one of them at a time.

7) Hotplug up frequency (hotplug_freq_1_1) should be greater than hotplug down frequency (hotplug_freq_2_0). Also, hotplug_down frequency should be greater than your scaling minimum frequency. Else second core might not turn off after it kicks in.

8) Hotplug runqueues values affects second core activate/deactivate decisions based on no of threads running or no of processes kept in run queue. Let their values be between 200 and 350. If you need second to turn on quickly and turn off slowly, use low values for up rq and down rq.

9) freq_for_responsiveness is the frequency that aids in recalculating a frequency_next to scale down to from maximum frequency. When i) that frequency_next is found to be less than value of freq_for_responsiveness and ii) if by scaling down to that frequency, next sample won't cause a scale down, then the frequency_next is set to freq_for_responsiveness. (This prevents scaling down to a low frequency where next sample will cause a scale up). A frequency in the bottom half of your frequency table is a sensible value for this parameter. To disable use of this param, set it to your scaling minimum frequency.

10) up_threshold_at_min_freq is the up threshold for frequencies below freq_for_responsiveness. Value of this should depend on how low or high your freq_for_responsiveness is. If you need relaxed scaling till freq_for_responsiveness, use higher values for up_threshold_at_min_freq. And vice-verse.