Bug 1393960

Summary: [RFE] Dynamic profile switching based on current power state
Product: [Fedora] Fedora Reporter: Michal Sekletar <msekleta>
Component: tunedAssignee: Jaroslav Škarvada <jskarvad>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: unspecified    
Version: rawhideCC: jskarvad, pknirsch, tkorbar
Target Milestone: ---Keywords: FutureFeature
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Michal Sekletar 2016-11-10 17:34:42 UTC
Description of problem:
When my laptop is docked I'd like to use "throughput-performance" tuned profile. But when it is running on battery I'd like to use "powersave" profile (for workloads like internet browsing and reading emails). I can switch profiles manually, but it would be great if I could tell tuned to do it automatically when power state of the machine changes.

Version-Release number of selected component (if applicable):
tuned-2.7.1-3.fc26

Actual results:
No such configuration option available.

Expected results:
Options like on_ac_profile= on_battery_profile= for /etc/tuned/tuned-main.conf.

Comment 1 Jaroslav Škarvada 2016-11-10 17:41:24 UTC
Thanks for the RFE, I have been asked for this functionality several times, usually at conferences during Q&A. Even if this approach is not generally recommended, i.e. it's usually more energetically efficient to finish task on full speed in shorter time than running throttled for longer time, I think this feature would find its users. E.g. it could be beneficial when surfing web from battery, browsing social networks, chatting on IRC, etc. I am going to add this functionality, switch it off by default, but it will be easy to enable it through the configuration.

Comment 2 Ondřej Lysoněk 2017-08-09 14:24:21 UTC
I think I just came up with a simple solution to this, which uses the recommend.d functionality, recently implemented in upstream.

We could provide a recommend configuration file, which would have rules saying which profile should be activated in different power states. Then some udev (or acpi?) hook would be written, which would get activated on power state change, and which would restart Tuned. Tuned would then switch to the recommended profile according to the power state.

Comment 3 Jaroslav Škarvada 2017-08-09 14:46:45 UTC
(In reply to Ondřej Lysoněk from comment #2)
> I think I just came up with a simple solution to this, which uses the
> recommend.d functionality, recently implemented in upstream.
> 
> We could provide a recommend configuration file, which would have rules
> saying which profile should be activated in different power states. Then
> some udev (or acpi?) hook would be written, which would get activated on
> power state change, and which would restart Tuned. Tuned would then switch
> to the recommended profile according to the power state.

Maybe we could add 'power' key/check into the recommend.d configuration, e.g.:
[powersave]
power=battery

[throughput-performance]
power=ac

Or it could also do percentage, e.g.:

[powersave]
power=<10%

Would mean that it will change to powersve if every battery on the system is bellow 10%. Or maybe more complex:

[powersave]
power=BAT1<10%

Would switch to powersave if BAT1 is bellow 10%.

We could poll 'upower' at the main loop, or e.g. each 10th activation of the main loop - I think it's not time criticial. Upower has DBus API and also broadcasts state changes on the DBus, so for the AC/BAT change, we could just listen for the event on the DBus or asynchronously query it in the main loop (probably more robust).

I would prefer built-in functionality over the udev hooks/hacks.

Comment 4 Fedora Update System 2019-02-25 12:53:53 UTC
cheat-2.5.1-1.fc28 has been submitted as an update to Fedora 28. https://bodhi.fedoraproject.org/updates/FEDORA-2019-90e2fc2614

Comment 5 Ondřej Lysoněk 2019-02-25 13:07:59 UTC
Please disregard comment#4, it got added by accident.

Comment 6 Tomas Korbar 2019-02-25 15:09:50 UTC
Hi,
I'm currently trying to implement this feature and i've come across a problem.
I proposed this way how to work with power conditions: 
I will add power monitor to tuned.
Tuned will read recommend file and if some profile fullfills its conditions before profile with power conditions is read then it is set and power monitor is not started.
In the other case when recommend method hits profile with power conditions then it starts power monitor and registers this conditions in it.
From this moment power monitor will watch over batteries or power lines and if some power condition is fulfilled then it again invokes recommendation method which eventually changes profile.
Here is the problem. Should recommend method process again all conditions for profiles until some profiles's conditions are fulfilled like on start up or process just profiles which contains power condition?
Tell me your opinion please.

Comment 7 Jaroslav Škarvada 2019-02-25 15:16:18 UTC
(In reply to Tomas Korbar from comment #6)
Hi, thanks for looking at it. I am inclining to 'periodical re-evaluation of the power conditions', i.e. not evaluating all conditions. My opinion is that it's the most safe and backward compatible approach. Drawback: some power rules will have to be more complex. Just my two cents, other opinions?

Comment 8 Ondřej Lysoněk 2019-02-26 11:07:07 UTC
To make sure we're on the same page here, by "power conditions" we mean
e.g. the line "power=battery" in the following recommend.conf file, correct?
[powersave]
power=battery

(In reply to Tomas Korbar from comment #6)
> Tuned will read recommend file and if some profile fullfills its conditions
> before profile with power conditions is read then it is set and power
> monitor is not started.
> In the other case when recommend method hits profile with power conditions
> then it starts power monitor and registers this conditions in it.

Makes sense regarding starting vs. not starting the power monitor.

BTW, I don't think the power monitor needs to be (or even should be)
implemented as a descendant of the tuned.monitors.base.Monitor class.
The monitors that we currently have are used for different purposes than
the power monitor, so it can be implemented completely differently.

> Here is the problem. Should recommend method process again all conditions
> for profiles until some profiles's conditions are fulfilled like on start up
> or process just profiles which contains power condition?

So you're not sure, whether the recommended profile should change based
on changes in the system other than the power status. Do I understand
that correctly?

I think it should not. Only changes in the power status should be considered.
Otherwise the changes that do not relate to the power status would get
re-evaluated at random times - at times when a power status change happens.

Comment 9 Ondřej Lysoněk 2019-02-26 11:07:42 UTC
After some meditation, here's how I think it could work :)

To illustrate what I'm talking about here, I'll be working with the following
example recommend.conf.

[atomic-host]
system=.*atomic.*

[balanced]
system=.*workstation.*
power=battery

[throughput-performance]


Recommend.conf files evaluation during Tuned startup
----------------------------------------------------
In the first phase, Tuned should read all the recommend.conf files, in their
entirety (i.e., it should not stop reading them after a match is found) (*).

In the second phase, it should find all matching profiles, while ignoring all
the power-related conditions. Tuned should then store the matching profiles
and the corresponding power-related conditions in some kind of cache (**).
The resulting data structure could look something like this, supposing that
the "system=.*atomic.*" condition evaluates to false, but the
"system=.*workstation.*" condition evaluates to true:

[
  { "balanced": [ "power=battery" ] },
  { "throughput-performance": [] },
]

In the third phase, Tuned should evaluate the above data structure in order to
find the final recommended profile. This time, it should consider the
power-related conditions. The data structure should be processed in order.
After finding the first match, the evaluation stops and the matching profile
will be the recommended profile.

In our example, supposing that the system is running on battery, the resulting
recommended profile would be "balanced".

Changing the active profile based on power status changes during runtime
------------------------------------------------------------------------
During runtime, Tuned continuously monitors the power status. When a change
in the power status happens, Tuned should re-evaluate the cached data
structure, in the same way as in the "third phase" above. If the resulting
recommended profile is different than the profile that is currently active,
the new recommended profile should be applied.


Notice that according to the above description, the power monitor is always
started. But that does not need to be the case - if the first item of the
cached data structure does not have any power-related conditions, then some
of the steps can be skipped and the power monitor does not need to be started.

Also note that the power monitoring should not be started if profile_mode is
manual.

(*) (**)  The consequence of this is that:
    1. all recommend.conf files are read only once,
    2. all non-power-related conditions are evaluated only once.

    This is a good thing. Otherwise recommend.conf would get re-read and
    non-power-related conditions would get re-evaluated at random times, i.e.
    at times when the power status changes.


If any of the above is not clear, or you disagree with something, it would
probably be more efficient to discuss it in person.

Comment 10 Ondřej Lysoněk 2019-02-26 11:08:00 UTC
Some other things to consider:
1. Should be allow disabling the power monitoring, so that the active
   profile does not change in response to changes in the power status?
2. Should we allow disabling processing the power-related conditions in
   recommend.conf files altogether? It would allow making the profile
   choice solely based on "static" factors (such as the contents of
   /etc/os-release), while ignoring "dynamic" factors (such as the power
   status).

   If we allowed it, then it would have implications on the way the
   recommend.conf files need to be written - they would have to be ordered in
   particular way, so that they're still useful even if power-related
   conditions are ignored.
3. Is the design, outlined in the previous commit, extensible with monitors
   other than the power monitor? For example, if we decided that we want
   to have an inotify monitor that would change the profile based on changes
   in the filesystem, would there be a natural way to extend the profile
   selection algorithm?

Comment 11 Ondřej Lysoněk 2019-02-26 11:08:35 UTC
This is a high-impact feature with lots of details that need to be thought out. 
So let's not rush it. Let's do it right. Otherwise we could end up with
a fundamentally broken design.