Skip to content

Commit

Permalink
[Feature] Force use of powersave or performance governors (#476)
Browse files Browse the repository at this point in the history
* add the --force option and governor overrides

* update README to reflect --force option

* add --state option

* update README with --state option

* update README to expand on --force functionality

* change name of remove() func and remove pickle upon --remove

* check if daemon is not running when using --force and change --state

* add links to README

* change force section wording

* add quotes to --force help

* add override warning to stats file

* hide --get-state flag

* consolidate error messages and add daemon checks to --get-state and --stats

* add quotes
  • Loading branch information
shadeyg56 committed Feb 1, 2023
1 parent f66df2a commit 2bfe71e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 33 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ auto-cpufreq is looking for [co-maintainers & open source developers to help sha
* [auto-cpufreq modes and options](https://github.com/AdnanHodzic/auto-cpufreq/#auto-cpufreq-modes-and-options)
* [monitor](https://github.com/AdnanHodzic/auto-cpufreq/#monitor)
* [live](https://github.com/AdnanHodzic/auto-cpufreq/#live)
* [overriding governor](https://github.com/AdnanHodzic/auto-cpufreq/#overriding-governor)
* [Install - auto-cpufreq daemon](https://github.com/AdnanHodzic/auto-cpufreq/#install---auto-cpufreq-daemon)
* [Remove - auto-cpufreq daemon](https://github.com/AdnanHodzic/auto-cpufreq/#remove---auto-cpufreq-daemon)
* [stats](https://github.com/AdnanHodzic/auto-cpufreq/#stats)
Expand Down Expand Up @@ -207,7 +208,10 @@ auto-cpufreq should be run with with one of the following options:
* [stats](https://github.com/AdnanHodzic/auto-cpufreq/#stats)
- View live stats of CPU optimizations made by daemon

* config TEXT
* [force=TEXT](https://github.com/AdnanHodzic/auto-cpufreq/#overriding-governor)
- Force use of either the "powersave" or "performance" governor. Setting to "reset" goes back to normal mode

* config=TEXT
- Use config file at defined path

* debug
Expand Down Expand Up @@ -238,6 +242,13 @@ No changes are made to the system, and is solely made for demonstration purposes

Necessary changes are temporarily made to the system which are lost with system reboot. This mode is made to evaluate what the system would behave with auto-cpufreq permanently running on the system.

### Overriding governor

`sudo auto-cpufreq --force=governor`

Force use of either "powersave" or "performance" governors. Setting to "reset" will go back to normal mode
Please note that any set override will persist even after reboot.

### Install - auto-cpufreq daemon

Necessary changes are made to the system for auto-cpufreq CPU optimization to persist across reboots. The daemon is deployed and then started as a systemd service. Changes are made automatically and live stats are generated for monitoring purposes.
Expand Down
75 changes: 55 additions & 20 deletions auto_cpufreq/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import distro
import time
import click
import pickle
import warnings
import configparser
import pkg_resources
Expand Down Expand Up @@ -57,6 +58,9 @@
auto_cpufreq_stats_path = None
auto_cpufreq_stats_file = None

# track governor override
STORE = "/opt/auto-cpufreq/venv/override.pickle"

if os.getenv("PKG_MARKER") == "SNAP":
auto_cpufreq_stats_path = Path("/var/snap/auto-cpufreq/current/auto-cpufreq.stats")
else:
Expand All @@ -71,7 +75,6 @@ def file_stats():
auto_cpufreq_stats_file = open(auto_cpufreq_stats_path, "w")
sys.stdout = auto_cpufreq_stats_file


def get_config(config_file=""):
if not hasattr(get_config, "config"):
get_config.config = configparser.ConfigParser()
Expand All @@ -82,6 +85,26 @@ def get_config(config_file=""):

return get_config.config

def get_override():
if os.path.isfile(STORE):
with open(STORE, "rb") as store:
return pickle.load(store)
else:
return "default"

def set_override(override):
if override in ["powersave", "performance"]:
with open(STORE, "wb") as store:
pickle.dump(override, store)
print(f"Set governor override to {override}")
elif override == "reset":
if os.path.isfile(STORE):
os.remove(STORE)
print("Governor override removed")
elif override is not None:
print("Invalid option.\nUse force=performance, force=powersave, or force=reset")



# get distro name
try:
Expand Down Expand Up @@ -314,14 +337,6 @@ def footer(l=79):
print("\n" + "-" * l + "\n")


def daemon_not_found():
print("\n" + "-" * 32 + " Daemon check " + "-" * 33 + "\n")
print(
"ERROR:\n\nDaemon not enabled, must run install first, i.e: \nsudo auto-cpufreq --install"
)
footer()


def deploy_complete_msg():
print("\n" + "-" * 17 + " auto-cpufreq daemon installed and running " + "-" * 17 + "\n")
print("To view live stats, run:\nauto-cpufreq --stats")
Expand Down Expand Up @@ -404,7 +419,7 @@ def deploy_daemon_performance():


# remove auto-cpufreq daemon
def remove():
def remove_daemon():

# check if auto-cpufreq is installed
if not os.path.exists("/usr/local/bin/auto-cpufreq-remove"):
Expand All @@ -426,6 +441,10 @@ def remove():
# remove auto-cpufreq-remove
os.remove("/usr/local/bin/auto-cpufreq-remove")

# delete override pickle if it exists
if os.path.exists(STORE):
os.remove(STORE)

# delete stats file
if auto_cpufreq_stats_path.exists():
if auto_cpufreq_stats_file is not None:
Expand Down Expand Up @@ -580,6 +599,8 @@ def set_powersave():
else:
gov = get_avail_powersave()
print(f'Setting to use: "{gov}" governor')
if get_override() != "default":
print("Warning: governor overwritten using `--force` flag.")
run(f"cpufreqctl.auto-cpufreq --governor --set={gov}", shell=True)
if (
Path("/sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference").exists()
Expand Down Expand Up @@ -786,6 +807,8 @@ def set_performance():
gov = get_avail_performance()

print(f'Setting to use: "{gov}" governor')
if get_override() != "default":
print("Warning: governor overwritten using `--force` flag.")
run(
f"cpufreqctl.auto-cpufreq --governor --set={gov}",
shell=True,
Expand Down Expand Up @@ -997,7 +1020,12 @@ def set_autofreq():
print("\n" + "-" * 28 + " CPU frequency scaling " + "-" * 28 + "\n")

# determine which governor should be used
if charging():
override = get_override()
if override == "powersave":
set_powersave()
elif override == "performance":
set_performance()
elif charging():
print("Battery is: charging\n")
set_performance()
else:
Expand Down Expand Up @@ -1149,20 +1177,12 @@ def sysinfo():
print("\nCPU fan speed:", psutil.sensors_fans()[current_fan][0].current, "RPM")


def no_stats_msg():
print("\n" + "-" * 29 + " auto-cpufreq stats " + "-" * 30 + "\n")
print(
'ERROR: auto-cpufreq stats are missing.\n\nMake sure to run: "auto-cpufreq --install" first'
)


# read stats func
def read_stats():
# read stats
if os.path.isfile(auto_cpufreq_stats_path):
call(["tail", "-n 50", "-f", str(auto_cpufreq_stats_path)], stderr=DEVNULL)
else:
no_stats_msg()
footer()


Expand All @@ -1187,12 +1207,27 @@ def daemon_running_msg():
)
footer()

def daemon_not_running_msg():
print("\n" + "-" * 24 + " auto-cpufreq not running " + "-" * 30 + "\n")
print(
"ERROR: auto-cpufreq is not running in daemon mode.\n\nMake sure to run \"sudo auto-cpufreq --install\" first"
)
footer()

# check if auto-cpufreq --daemon is running
def running_daemon():
def running_daemon_check():
if is_running("auto-cpufreq", "--daemon"):
daemon_running_msg()
exit(1)
elif os.getenv("PKG_MARKER") == "SNAP" and dcheck == "enabled":
daemon_running_msg()
exit(1)

# check if auto-cpufreq --daemon is not running
def not_running_daemon_check():
if not is_running("auto-cpufreq", "--daemon"):
daemon_not_running_msg()
exit(1)
elif os.getenv("PKG_MARKER") == "SNAP" and dcheck == "disabled":
daemon_not_running_msg()
exit(1)
36 changes: 24 additions & 12 deletions bin/auto-cpufreq
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ from auto_cpufreq.power_helper import *
@click.command()
@click.option("--monitor", is_flag=True, help="Monitor and see suggestions for CPU optimizations")
@click.option("--live", is_flag=True, help="Monitor and make (temp.) suggested CPU optimizations")
@click.option(
"--install/--remove",
default=True,
help="Install/remove daemon for (permanent) automatic CPU optimizations",
)
@click.option("--install", is_flag=True, help="Install daemon for (permanent) automatic CPU optimizations")
@click.option("--remove", is_flag=True, help="Remove daemon for (permanent) automatic CPU optimizations")

@click.option("--install_performance", is_flag=True, help="Install daemon in \"performance\" mode, reference:\n https://bit.ly/3bjVZW1")
@click.option("--stats", is_flag=True, help="View live stats of CPU optimizations made by daemon")
@click.option("--force", is_flag=False, help="Force use of either \"powersave\" or \"performance\" governors. Setting to \"reset\" will go back to normal mode")
@click.option("--get-state", is_flag=True, hidden=True)
@click.option(
"--config",
is_flag=False,
Expand All @@ -36,16 +36,23 @@ from auto_cpufreq.power_helper import *
@click.option("--donate", is_flag=True, help="Support the project")
@click.option("--log", is_flag=True, hidden=True)
@click.option("--daemon", is_flag=True, hidden=True)
def main(config, daemon, debug, install, install_performance, live, log, monitor, stats, version, donate):
def main(config, daemon, debug, install, remove, install_performance, live, log, monitor, stats, version, donate, force, get_state):

# display info if config file is used
def config_info_dialog():
if get_config(config) and hasattr(get_config, "using_cfg_file"):
print("\nUsing settings defined in " + config + " file")

# set governor override unless None or invalid
if force is not None:
not_running_daemon_check()
set_override(force)

if len(sys.argv) == 1:

print("\n" + "-" * 32 + " auto-cpufreq " + "-" * 33 + "\n")
print("Automatic CPU speed & power optimizer for Linux")

print("\nExample usage:\nauto-cpufreq --monitor")
print("\n-----\n")

Expand Down Expand Up @@ -92,7 +99,7 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
tlp_service_detect()
while True:
time.sleep(1)
running_daemon()
running_daemon_check()
footer()
gov_check()
cpufreqctl()
Expand All @@ -114,7 +121,7 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
tlp_service_detect()
while True:
try:
running_daemon()
running_daemon_check()
footer()
gov_check()
cpufreqctl()
Expand All @@ -127,6 +134,7 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
print("")
sys.exit()
elif stats:
not_running_daemon_check()
config_info_dialog()
print('\nNote: You can quit stats mode by pressing "ctrl+c"')
if os.getenv("PKG_MARKER") == "SNAP":
Expand All @@ -138,6 +146,10 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
read_stats()
elif log:
deprecated_log_msg()
elif get_state:
not_running_daemon_check()
override = get_override()
print(override)
elif debug:
# ToDo: add status of GNOME Power Profile service status
config_info_dialog()
Expand Down Expand Up @@ -181,14 +193,14 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
"Reference: https://github.com/AdnanHodzic/auto-cpufreq#configuring-auto-cpufreq\n")
else:
root_check()
running_daemon()
running_daemon_check()
gov_check()
deploy_daemon_performance()
deploy_complete_msg()
elif install:
if os.getenv("PKG_MARKER") == "SNAP":
root_check()
running_daemon()
running_daemon_check()
gnome_power_detect_snap()
tlp_service_detect_snap()
bluetooth_notif_snap()
Expand All @@ -198,7 +210,7 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
deploy_complete_msg()
else:
root_check()
running_daemon()
running_daemon_check()
gov_check()
deploy_daemon()
deploy_complete_msg()
Expand All @@ -218,7 +230,7 @@ def main(config, daemon, debug, install, install_performance, live, log, monitor
remove_complete_msg()
else:
root_check()
remove()
remove_daemon()
remove_complete_msg()


Expand Down

0 comments on commit 2bfe71e

Please sign in to comment.