machine: fix perfomance regression

The `update_service_status()` method could result in the creation of multiple subprocesses for each update, resulting in a performance hit as subprocesses are inherently expensive.

Fetch the state for all detected services in a single subprocess.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2021-11-03 09:10:12 -04:00
parent 6a39bbd0c3
commit 105858b0c7
1 changed files with 18 additions and 16 deletions

View File

@ -386,27 +386,29 @@ class Machine:
} }
async def update_service_status(self, notify: bool = True) -> None: async def update_service_status(self, notify: bool = True) -> None:
if not self.available_services:
return
svcs = self.system_info['available_services']
shell_cmd: SCMDComp = self.server.lookup_component('shell_command') shell_cmd: SCMDComp = self.server.lookup_component('shell_command')
for svc, state in list(self.available_services.items()): scmd = shell_cmd.build_shell_command(
scmd = shell_cmd.build_shell_command( "systemctl show -p ActiveState,SubState --value "
f"systemctl show -p ActiveState,SubState --value {svc}") f"{' '.join(svcs)}")
try: try:
resp = await scmd.run_with_response(log_complete=False) resp = await scmd.run_with_response(log_complete=False)
active_state, sub_state = resp.strip().split('\n', 1) for svc, state in zip(svcs, resp.strip().split('\n\n')):
active_state, sub_state = state.split('\n', 1)
new_state: Dict[str, str] = { new_state: Dict[str, str] = {
'active_state': active_state, 'active_state': active_state,
'sub_state': sub_state 'sub_state': sub_state
} }
except Exception: if self.available_services[svc] != new_state:
new_state = { self.available_services[svc] = new_state
'active_state': "error", if notify:
'sub_state': "error" self.server.send_event(
} "machine:service_state_changed",
if state != new_state and notify: {svc: new_state})
self.server.send_event("machine:service_state_changed", except Exception:
{svc: new_state}) logging.exception("Error processing service state update")
self.available_services[svc] = new_state
def load_component(config: ConfigHelper) -> Machine: def load_component(config: ConfigHelper) -> Machine:
return Machine(config) return Machine(config)