From 3106b395665649427afa08cde65e42a9cd12dce8 Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Tue, 26 Aug 2025 08:26:55 +1000 Subject: [PATCH] CPU optimizartion work 2 #1144 --- server/__main__.py | 6 ++-- server/initialise.py | 7 ++-- server/plugin.py | 81 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 72 insertions(+), 22 deletions(-) diff --git a/server/__main__.py b/server/__main__.py index 0385201e..426727e6 100755 --- a/server/__main__.py +++ b/server/__main__.py @@ -93,6 +93,7 @@ def main (): mylog('debug', '[MAIN] Starting loop') all_plugins = None + pm = None # -- SETTINGS BACKWARD COMPATIBILITY START -- # rename settings that have changed names due to code cleanup or migration to plugins @@ -102,10 +103,7 @@ def main (): while True: # re-load user configuration and plugins - all_plugins, imported = importConfigs(db, all_plugins) - - # initiate plugin manager - pm = plugin_manager(db, all_plugins) + pm, all_plugins, imported = importConfigs(pm, db, all_plugins) # update time started conf.loop_start_time = timeNowTZ() diff --git a/server/initialise.py b/server/initialise.py index a329870d..5bd8aa3d 100755 --- a/server/initialise.py +++ b/server/initialise.py @@ -112,7 +112,7 @@ def update_or_append(settings_list, item_tuple, key): #------------------------------------------------------------------------------- -def importConfigs (db, all_plugins): +def importConfigs (pm, db, all_plugins): sql = db.sql @@ -134,7 +134,7 @@ def importConfigs (db, all_plugins): if (fileModifiedTime == conf.lastImportedConfFile) and all_plugins is not None: mylog('debug', ['[Import Config] skipping config file import']) - return all_plugins, False + return pm, all_plugins, False # Header updateState("Import config", showSpinner = True) @@ -413,6 +413,7 @@ def importConfigs (db, all_plugins): # run plugins that are modifying the config pm = plugin_manager(db, all_plugins) + pm.clear_cache() pm.run_plugin_scripts('before_config_save') # Used to determine the next import @@ -431,7 +432,7 @@ def importConfigs (db, all_plugins): # front end app log loggging write_notification(msg, 'info', timeNowTZ()) - return all_plugins, True + return pm, all_plugins, True diff --git a/server/plugin.py b/server/plugin.py index 876ff741..e80a3604 100755 --- a/server/plugin.py +++ b/server/plugin.py @@ -27,9 +27,29 @@ class plugin_manager: self.db = db self.all_plugins = all_plugins + # object cache of settings and schedules for faster lookups + self._cache = {} + self._build_cache() + # Make sure log level is initialized correctly Logger(get_setting_value('LOG_LEVEL')) + def _build_cache(self): + """Build a cache of settings and schedules for faster lookups.""" + self._cache["settings"] = { + p["unique_prefix"]: { + "RUN": get_plugin_setting_obj(p, "RUN"), + "CMD": get_plugin_setting_obj(p, "CMD"), + } + for p in self.all_plugins + } + self._cache["schedules"] = {s.service: s for s in conf.mySchedules} + + def clear_cache(self): + """Force rebuild of the cache (e.g. after config reload).""" + self._cache = {} + self._build_cache() + #------------------------------------------------------------------------------- def run_plugin_scripts(self, runType): @@ -43,34 +63,65 @@ class plugin_manager: shouldRun = False prefix = plugin["unique_prefix"] - set = get_plugin_setting_obj(plugin, "RUN") + # 🔹 Lookup RUN setting from cache instead of calling get_plugin_setting_obj each time + run_setting = self._cache["settings"].get(prefix, {}).get("RUN") + + # set = get_plugin_setting_obj(plugin, "RUN") # mylog('debug', [f'[run_plugin_scripts] plugin: {plugin}']) # mylog('debug', [f'[run_plugin_scripts] set: {set}']) - if set != None and set['value'] == runType: + # if set != None and set['value'] == runType: + # if runType != "schedule": + # shouldRun = True + # elif runType == "schedule": + # # run if overdue scheduled time + # # check schedules if any contains a unique plugin prefix matching the current plugin + # for schd in conf.mySchedules: + # if schd.service == prefix: + # # Check if schedule overdue + # shouldRun = schd.runScheduleCheck() + if run_setting != None and run_setting['value'] == runType: if runType != "schedule": shouldRun = True - elif runType == "schedule": - # run if overdue scheduled time - # check schedules if any contains a unique plugin prefix matching the current plugin - for schd in conf.mySchedules: - if schd.service == prefix: - # Check if schedule overdue - shouldRun = schd.runScheduleCheck() + elif runType == "schedule": + # run if overdue scheduled time + # 🔹 Lookup schedule from cache instead of scanning conf.mySchedules + schd = self._cache["schedules"].get(prefix) + if schd: + # Check if schedule overdue + shouldRun = schd.runScheduleCheck() + # if shouldRun: + # # Header + # updateState(f"Plugin: {prefix}") + + # print_plugin_info(plugin, ['display_name']) + # mylog('debug', ['[Plugins] CMD: ', get_plugin_setting_obj(plugin, "CMD")["value"]]) + # execute_plugin(self.db, self.all_plugins, plugin) + # # update last run time + # if runType == "schedule": + # for schd in conf.mySchedules: + # if schd.service == prefix: + # # note the last time the scheduled plugin run was executed + # schd.last_run = timeNowTZ() if shouldRun: # Header updateState(f"Plugin: {prefix}") print_plugin_info(plugin, ['display_name']) - mylog('debug', ['[Plugins] CMD: ', get_plugin_setting_obj(plugin, "CMD")["value"]]) + + # 🔹 CMD also retrieved from cache + cmd_setting = self._cache["settings"].get(prefix, {}).get("CMD") + mylog('debug', ['[Plugins] CMD: ', cmd_setting["value"] if cmd_setting else None]) + execute_plugin(self.db, self.all_plugins, plugin) - # update last run time + + # update last run time if runType == "schedule": - for schd in conf.mySchedules: - if schd.service == prefix: - # note the last time the scheduled plugin run was executed - schd.last_run = timeNowTZ() + schd = self._cache["schedules"].get(prefix) + if schd: + # note the last time the scheduled plugin run was executed + schd.last_run = timeNowTZ() #=============================================================================== # Handling of user initialized front-end events