CpuLoadTrigger: support low threshold instead of cooldown period

This commit is contained in:
2025-03-29 21:35:57 +01:00
parent 798d25e75c
commit a56c3ed36f
3 changed files with 54 additions and 40 deletions
+8 -6
View File
@@ -46,20 +46,22 @@
</trigger> </trigger>
<trigger> <trigger>
<name>cpu_load</name> <name>cpu_load</name>
<logLevel>Info</logLevel> <logLevel>Debug</logLevel>
<type>sync</type> <type>sync</type>
<intervalInSeconds>5</intervalInSeconds> <intervalInSeconds>5</intervalInSeconds>
<governor>performance</governor> <governor>performance</governor>
<customConfig> <customConfig>
<oneMinuteLoadThreshold>0.3</oneMinuteLoadThreshold> <oneMinuteHighThreshold>0.35</oneMinuteHighThreshold>
<fiveMinuteLoadThreshold>0.2</fiveMinuteLoadThreshold> <fiveMinuteHighThreshold>0.25</fiveMinuteHighThreshold>
<tenMinuteLoadThreshold>0.1</tenMinuteLoadThreshold> <tenMinuteHighThreshold>0.15</tenMinuteHighThreshold>
<cooldownPeriodInMinutes>3</cooldownPeriodInMinutes> <oneMinuteLowThreshold>0.3</oneMinuteLowThreshold>
<fiveMinuteLowThreshold>0.2</fiveMinuteLowThreshold>
<tenMinuteLowThreshold>0.1</tenMinuteLowThreshold>
</customConfig> </customConfig>
</trigger> </trigger>
<trigger> <trigger>
<name>roon_arc</name> <name>roon_arc</name>
<logLevel>Debug</logLevel> <logLevel>Info</logLevel>
<type>async</type> <type>async</type>
<intervalInSeconds>5</intervalInSeconds> <intervalInSeconds>5</intervalInSeconds>
<governor>performance</governor> <governor>performance</governor>
+45 -33
View File
@@ -2,33 +2,43 @@ from cpu_governor_auto_adjust.trigger import Trigger
from cpu_governor_auto_adjust.config import Config from cpu_governor_auto_adjust.config import Config
from functools import cached_property from functools import cached_property
from os import getloadavg from os import getloadavg
from datetime import datetime, timedelta
class CpuLoadTrigger(Trigger): class CpuLoadTrigger(Trigger):
def __init__(self, _config: Config) -> None: def __init__(self, _config: Config) -> None:
super().__init__(_config) super().__init__(_config)
self.timestamp_last_governor_change = datetime.now() - timedelta(minutes=self.cooldown_period_in_minutes + 1)
@cached_property @cached_property
def one_minute_load_threshold(self) -> float: def one_minute_high_threshold(self) -> float:
return float(self.config.custom_config['oneMinuteLoadThreshold']) return float(self.config.custom_config['oneMinuteHighThreshold'])
@cached_property @cached_property
def five_minute_load_threshold(self) -> float: def five_minute_high_threshold(self) -> float:
return float(self.config.custom_config['fiveMinuteLoadThreshold']) return float(self.config.custom_config['fiveMinuteHighThreshold'])
@cached_property @cached_property
def ten_minute_load_threshold(self) -> float: def ten_minute_high_threshold(self) -> float:
return float(self.config.custom_config['tenMinuteLoadThreshold']) return float(self.config.custom_config['tenMinuteHighThreshold'])
@cached_property @cached_property
def threshold(self) -> tuple[float, float, float]: def high_threshold(self) -> tuple[float, float, float]:
return self.one_minute_load_threshold, self.five_minute_load_threshold, self.ten_minute_load_threshold return self.one_minute_high_threshold, self.five_minute_high_threshold, self.ten_minute_high_threshold
@cached_property @cached_property
def cooldown_period_in_minutes(self) -> float: def one_minute_low_threshold(self) -> float:
return float(self.config.custom_config['cooldownPeriodInMinutes']) return float(self.config.custom_config['oneMinuteLowThreshold'])
@cached_property
def five_minute_low_threshold(self) -> float:
return float(self.config.custom_config['fiveMinuteLowThreshold'])
@cached_property
def ten_minute_low_threshold(self) -> float:
return float(self.config.custom_config['tenMinuteLowThreshold'])
@cached_property
def low_threshold(self) -> tuple[float, float, float]:
return self.one_minute_low_threshold, self.five_minute_low_threshold, self.ten_minute_low_threshold
@property @property
def current_load(self) -> tuple[float, float, float]: def current_load(self) -> tuple[float, float, float]:
@@ -36,35 +46,37 @@ class CpuLoadTrigger(Trigger):
self.log.debug("current load: %s", _current_load) self.log.debug("current load: %s", _current_load)
return _current_load return _current_load
def current_load_average_over_threshold(self) -> bool: @property
return any(load >= threshold for load, threshold in zip(self.current_load, self.threshold)) def current_load_average_over_high_threshold(self) -> bool:
return any(load >= threshold for load, threshold in zip(self.current_load, self.high_threshold))
@property
def current_load_average_over_under_threshold(self) -> bool:
return any(load <= threshold for load, threshold in zip(self.current_load, self.low_threshold))
def run(self) -> None: def run(self) -> None:
current_active = self.active current_active = self.active
current_time = datetime.now() new_high_load_active = self.current_load_average_over_high_threshold
new_active = self.current_load_average_over_threshold() new_low_load_active = self.current_load_average_over_under_threshold
if not current_active and new_active: if not current_active and new_high_load_active:
self.log.info( self.log.info(
"activating trigger, load: %s, threshold: %s, governor: %s", "activating trigger, load: %s, high threshold: %s, governor: %s",
self.current_load, self.threshold, self.governor.name self.current_load, self.high_threshold, self.governor.name
) )
self.timestamp_last_governor_change = current_time self.active = True
elif current_active and new_active: elif current_active and new_high_load_active:
self.log.debug("trigger is already active, load: %s, threshold: %s", self.current_load, self.threshold) self.log.debug(
self.timestamp_last_governor_change = current_time "trigger is already active, load: %s, high threshold: %s",
self.current_load, self.high_threshold
elif current_active and not new_active: )
if (current_time - timedelta(minutes=self.cooldown_period_in_minutes)) < self.timestamp_last_governor_change:
self.log.debug("cooldown period, staying on governor: %s, current load: %s", self.governor.name, self.current_load)
return
elif current_active and new_low_load_active:
self.log.info( self.log.info(
"deactivating trigger, load: %s, threshold: %s, governor: %s", "deactivating trigger, load: %s, low threshold: %s, governor: %s",
self.current_load, self.threshold, self.governor.name self.current_load, self.low_threshold, self.governor.name
) )
self.active = False
else: else:
self.log.debug("trigger is already inactive, load: %s, threshold: %s", self.current_load, self.threshold) self.log.debug("trigger is already inactive, load: %s, threshold: %s", self.current_load, self.high_threshold)
self.active = new_active
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "cpu_governor_auto_adjust" name = "cpu_governor_auto_adjust"
version = "0.2.9" version = "0.3.1"
description = "This application has been developed to automatically change cpu governor based on certain triggers." description = "This application has been developed to automatically change cpu governor based on certain triggers."
authors = [ authors = [
{ name = "Martin Reurekas", email = "martin@semrks.nl" } { name = "Martin Reurekas", email = "martin@semrks.nl" }