Signficantly reduce executor contention during bootstrap (#107312)

* Signficantly reduce executor contention during bootstrap

At startup we have a thundering herd wanting to use the executor
to load manifiest.json. Since we know which integrations we are
about to load in each resolver step, group the manifest loads
into single executor jobs by calling async_get_integrations on
the deps of the integrations after they are resolved.

In practice this reduced the number of executor jobs
by 80% during bootstrap

* merge

* naming

* tweak

* tweak

* not enough contention to be worth it there

* refactor to avoid waiting

* refactor to avoid waiting

* tweaks

* tweaks

* tweak

* background is fine

* comment
This commit is contained in:
J. Nick Koston
2024-01-07 17:55:40 -10:00
committed by GitHub
parent acf78664e2
commit 69307374f4
3 changed files with 60 additions and 5 deletions

View File

@@ -63,6 +63,13 @@ async def async_process_requirements(
await _async_get_manager(hass).async_process_requirements(name, requirements)
async def async_load_installed_versions(
hass: HomeAssistant, requirements: set[str]
) -> None:
"""Load the installed version of requirements."""
await _async_get_manager(hass).async_load_installed_versions(requirements)
@callback
def _async_get_manager(hass: HomeAssistant) -> RequirementsManager:
"""Get the requirements manager."""
@@ -284,3 +291,15 @@ class RequirementsManager:
self.install_failure_history |= failures
if failures:
raise RequirementsNotFound(name, list(failures))
async def async_load_installed_versions(
self,
requirements: set[str],
) -> None:
"""Load the installed version of requirements."""
if not (requirements_to_check := requirements - self.is_installed_cache):
return
self.is_installed_cache |= await self.hass.async_add_executor_job(
pkg_util.get_installed_versions, requirements_to_check
)