diff --git a/README.md b/README.md index f74ea105..ea7eb125 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,18 @@ Default location where config needs to be placed for it to be read automatically # preferred governor. governor = performance +# minimum cpu frequency (in kHz) +# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_min_freq = 800000 + +# maximum cpu frequency (in kHz) +# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_max_freq = 1000000 + # turbo boost setting. possible values: always, auto, never turbo = auto @@ -97,6 +109,18 @@ turbo = auto # preferred governor governor = powersave +# minimum cpu frequency (in kHz) +# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_min_freq = 800000 + +# maximum cpu frequency (in kHz) +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000 +# to use this feature, uncomment the following line and set the value accordingly +# scaling_max_freq = 1000000 + # turbo boost setting. possible values: always, auto, never turbo = auto ``` diff --git a/auto-cpufreq.conf-example b/auto-cpufreq.conf-example index 994dfe53..3a141ac2 100644 --- a/auto-cpufreq.conf-example +++ b/auto-cpufreq.conf-example @@ -1,20 +1,41 @@ -# configuration file for auto-cpufreq -# located in /etc/auto-cpufreq.conf - # settings for when connected to a power source [charger] # see available governors by running: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors # preferred governor. governor = performance +# minimum cpu frequency (in kHz) +# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_min_freq = 800000 + +# maximum cpu frequency (in kHz) +# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_max_freq = 1000000 + # turbo boost setting. possible values: always, auto, never turbo = auto -#settings for when using battery power +# settings for when using battery power [battery] # see available governors by running: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors # preferred governor governor = powersave +# minimum cpu frequency (in kHz) +# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000 +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# to use this feature, uncomment the following line and set the value accordingly +# scaling_min_freq = 800000 + +# maximum cpu frequency (in kHz) +# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html +# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000 +# to use this feature, uncomment the following line and set the value accordingly +# scaling_max_freq = 1000000 + # turbo boost setting. possible values: always, auto, never turbo = auto diff --git a/auto_cpufreq/core.py b/auto_cpufreq/core.py index 8c865a96..bb44ae24 100644 --- a/auto_cpufreq/core.py +++ b/auto_cpufreq/core.py @@ -70,16 +70,14 @@ def file_stats(): def get_config(config_file=""): - if not hasattr(get_config, "dict"): - get_config.dict = dict() + if not hasattr(get_config, "config"): + get_config.config = configparser.ConfigParser() - config = configparser.ConfigParser() - config.read(config_file) + if os.path.isfile(config_file): + get_config.config.read(config_file) + get_config.using_cfg_file = True - for section in config.sections(): - get_config.dict[section] = dict(config.items(section)) - - return get_config.dict + return get_config.config # get distro name @@ -457,12 +455,60 @@ def display_load(): print("Average temp. of all cores:", avg_all_core_temp, "°C", "\n") +# set minimum and maximum CPU frequencies +def set_frequencies(): + conf = get_config() + section = "charger" if charging() else "battery" + frequency = { + "scaling_max_freq": { + "cmdargs": "--frequency-max", + "minmax": "maximum", + "value": None, + }, + "scaling_min_freq": { + "cmdargs": "--frequency-min", + "minmax": "minimum", + "value": None, + }, + } + max_limit = None + min_limit = None + + for freq_type in ["scaling_max_freq", "scaling_min_freq"]: + if not conf.has_option(section, freq_type): + frequency.pop(freq_type) + + for freq_type in frequency.keys(): + try: + frequency[freq_type]["value"] = int(conf[section][freq_type].strip()) + except ValueError: + print(f"Invalid value for '{freq_type}': {frequency[freq_type]['value']}") + exit(1) + + if not max_limit: + max_limit = int(getoutput(f"cpufreqctl.auto-cpufreq --frequency-max-limit")) + if not min_limit: + min_limit = int(getoutput(f"cpufreqctl.auto-cpufreq --frequency-min-limit")) + + if not (min_limit <= frequency[freq_type]["value"] <= max_limit): + print( + f"Given value for '{freq_type}' is not within the allowed frequencies {min_limit}-{max_limit} kHz" + ) + exit(1) + + args = f"{frequency[freq_type]['cmdargs']} --set={frequency[freq_type]['value']}" + message = f'Setting {frequency[freq_type]["minmax"]} CPU frequency to {round(frequency[freq_type]["value"]/1000)} Mhz' + + # set the frequency + print(message) + run(f"cpufreqctl.auto-cpufreq {args}", shell=True) + + # set powersave and enable turbo def set_powersave(): - gov = get_config() - if "battery" in gov: - if "governor" in gov["battery"]: - gov = gov["battery"]["governor"] + conf = get_config() + if conf.has_option("battery", "governor"): + gov = conf["battery"]["governor"] else: gov = get_avail_powersave() print(f'Setting to use: "{gov}" governor') @@ -474,6 +520,9 @@ def set_powersave(): run("cpufreqctl.auto-cpufreq --epp --set=balance_power", shell=True) print('Setting to use: "balance_power" EPP') + # set frequencies + set_frequencies() + # get CPU utilization as a percentage cpuload = psutil.cpu_percent(interval=1) @@ -485,10 +534,8 @@ def set_powersave(): print("Average temp. of all cores:", avg_all_core_temp, "°C") # conditions for setting turbo in powersave - auto = get_config() - if "battery" in auto: - if "turbo" in auto["battery"]: - auto = auto["battery"]["turbo"] + if conf.has_option("battery", "turbo"): + auto = conf["battery"]["turbo"] else: auto = "auto" @@ -664,10 +711,9 @@ def mon_powersave(): # set performance and enable turbo def set_performance(): - gov = get_config() - if "charger" in gov: - if "governor" in gov["charger"]: - gov = gov["charger"]["governor"] + conf = get_config() + if conf.has_option("charger", "governor"): + gov = conf["charger"]["governor"] else: gov = get_avail_performance() @@ -683,6 +729,9 @@ def set_performance(): run("cpufreqctl.auto-cpufreq --epp --set=balance_performance", shell=True) print('Setting to use: "balance_performance" EPP') + # set frequencies + set_frequencies() + # get CPU utilization as a percentage cpuload = psutil.cpu_percent(interval=1) @@ -693,10 +742,8 @@ def set_performance(): print("Total system load:", load1m) print("Average temp. of all cores:", avg_all_core_temp, "°C") - auto = get_config() - if "charger" in auto: - if "turbo" in auto["charger"]: - auto = auto["charger"]["turbo"] + if conf.has_option("charger", "turbo"): + auto = conf["charger"]["turbo"] else: auto = "auto" diff --git a/bin/auto-cpufreq b/bin/auto-cpufreq index 88133a3d..1be521e0 100755 --- a/bin/auto-cpufreq +++ b/bin/auto-cpufreq @@ -10,7 +10,7 @@ import time import click from subprocess import call, run -sys.path.append('../') +sys.path.append("../") from auto_cpufreq.core import * from auto_cpufreq.power_helper import * @@ -18,9 +18,18 @@ 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/--remove", + default=True, + help="Install/remove daemon for (permanent) automatic CPU optimizations", +) @click.option("--stats", is_flag=True, help="View live stats of CPU optimizations made by daemon") -@click.option("--config", is_flag=False, default="/etc/auto-cpufreq.conf", help="Use config file at defined path") +@click.option( + "--config", + is_flag=False, + default="/etc/auto-cpufreq.conf", + help="Use config file at defined path", +) @click.option("--debug", is_flag=True, help="Show debug info (include when submitting bugs)") @click.option("--version", is_flag=True, help="Show currently installed version") @click.option("--donate", is_flag=True, help="Support the project") @@ -30,7 +39,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don # display info if config file is used def config_info_dialog(): - if bool(get_config(config)): + if get_config(config) and hasattr(get_config, "using_cfg_file"): print("\nUsing settings defined in " + config + " file") if len(sys.argv) == 1: @@ -73,7 +82,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don elif monitor: config_info_dialog() root_check() - print("\nNote: You can quit monitor mode by pressing \"ctrl+c\"") + print('\nNote: You can quit monitor mode by pressing "ctrl+c"') if os.getenv("PKG_MARKER") == "SNAP": gnome_power_detect_snap() tlp_service_detect_snap() @@ -93,7 +102,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don elif live: root_check() config_info_dialog() - print("\nNote: You can quit live mode by pressing \"ctrl+c\"") + print('\nNote: You can quit live mode by pressing "ctrl+c"') time.sleep(1) if os.getenv("PKG_MARKER") == "SNAP": gnome_power_detect_snap() @@ -112,7 +121,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don countdown(5) elif stats: config_info_dialog() - print("\nNote: You can quit stats mode by pressing \"ctrl+c\"") + print('\nNote: You can quit stats mode by pressing "ctrl+c"') if os.getenv("PKG_MARKER") == "SNAP": gnome_power_detect_snap() tlp_service_detect_snap() @@ -158,7 +167,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don print("https://github.com/AdnanHodzic/auto-cpufreq/#donate") footer() elif install: - if os.getenv('PKG_MARKER') == "SNAP": + if os.getenv("PKG_MARKER") == "SNAP": root_check() running_daemon() gnome_power_detect_snap() @@ -175,7 +184,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don deploy_daemon() deploy_complete_msg() elif remove: - if os.getenv('PKG_MARKER') == "SNAP": + if os.getenv("PKG_MARKER") == "SNAP": root_check() run("snapctl set daemon=disabled", shell=True) run("snapctl stop --disable auto-cpufreq", shell=True) @@ -184,7 +193,7 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don auto_cpufreq_stats_file.close() auto_cpufreq_stats_path.unlink() - # ToDo: + # ToDo: # * undo bluetooth boot disable gnome_power_rm_reminder_snap() remove_complete_msg() @@ -194,5 +203,5 @@ def main(config, daemon, debug, install, live, log, monitor, stats, version, don remove_complete_msg() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/scripts/cpufreqctl.sh b/scripts/cpufreqctl.sh index eb94599a..76ca0aac 100755 --- a/scripts/cpufreqctl.sh +++ b/scripts/cpufreqctl.sh @@ -40,23 +40,25 @@ function help () { echo "Usage:" echo " cpufreqctl [OPTION[=VALUE]...]" echo "" - echo " --help Show help options" - echo " --version Package version" - echo " --verbose, -v Verbose output" + echo " --help Show help options" + echo " --version Package version" + echo " --verbose, -v Verbose output" echo "" - echo " --set=VALUE Set VALUE for selected option" - echo " --core=NUMBER Apply selected option just for the core NUMBER (0 ~ N - 1)" - echo " --available Get available values instand of default: current" + echo " --set=VALUE Set VALUE for selected option" + echo " --core=NUMBER Apply selected option just for the core NUMBER (0 ~ N - 1)" + echo " --available Get available values instand of default: current" echo "" - echo " --driver Current processor driver" - echo " --governor Scaling governor's options" - echo " --epp Governor's energy_performance_preference options" - echo " --frequency Frequency options" - echo " --on Turn on --core=NUMBER" - echo " --off Turn off --core=NUMBER" - echo " --frequency-min Minimal frequency options" - echo " --frequency-max Maximum frequency options" - echo " --boost Current cpu boost value" + echo " --driver Current processor driver" + echo " --governor Scaling governor's options" + echo " --epp Governor's energy_performance_preference options" + echo " --frequency Frequency options" + echo " --on Turn on --core=NUMBER" + echo " --off Turn off --core=NUMBER" + echo " --frequency-min Minimal frequency options" + echo " --frequency-max Maximum frequency options" + echo " --frequency-min-limit Get minimal frequency limit" + echo " --frequency-max-limit Get maximum frequency limit" + echo " --boost Current cpu boost value" echo "" echo "intel_pstate options" echo " --no-turbo Current no_turbo value" @@ -230,6 +232,22 @@ function set_frequency_max () { fi } +function get_frequency_min_limit () { + if [ -z $CORE ] + then + CORE=0 + fi + cat /sys/devices/system/cpu/cpu$CORE/cpufreq/cpuinfo_min_freq +} + +function get_frequency_max_limit () { + if [ -z $CORE ] + then + CORE=0 + fi + cat /sys/devices/system/cpu/cpu$CORE/cpufreq/cpuinfo_max_freq +} + function get_energy_performance_preference () { if [ -z $CORE ] then @@ -385,6 +403,16 @@ then fi exit fi +if [ $OPTION = "--frequency-min-limit" ] +then + verbose "Getting CPU"$CORE" minimal frequency limit" + get_frequency_min_limit +fi +if [ $OPTION = "--frequency-max-limit" ] +then + verbose "Getting CPU"$CORE" maximum frequency limit" + get_frequency_max_limit +fi if [ $OPTION = "--min-perf" ] then if [ -z $VALUE ]