mirror of
https://github.com/esphome/esphome.git
synced 2026-09-21 20:18:43 +00:00
[core] Lazy-load esphome.core.config from loader and config
The top-level `import esphome.core.config` in `esphome/loader.py` (used
only to register the "esphome" pseudo-component in `_COMPONENT_CACHE`)
was pulling `esphome.automation` + `esphome.config_validation` eagerly
into every `esphome` CLI invocation, even fast paths like
`esphome version`. Move the cache registration into `_lookup_module`,
triggered on first `get_component("esphome")`.
Also defers the two `esphome.core.config` call sites inside
`esphome/config.py` (CoreFinalValidateStep and validate_config), which
were the other eager entry point.
Local `import esphome.__main__` drops from ~49ms to ~46ms; more
importantly, `esphome.core.config` / `esphome.automation` no longer
appear in the top offenders table, and `esphome.config_validation`
drops from 4.7ms self to 2.0ms self on CI.
This commit is contained in:
+8
-1
@@ -25,7 +25,10 @@ from esphome.const import (
|
||||
CONF_SUBSTITUTIONS,
|
||||
)
|
||||
from esphome.core import CORE, DocumentRange, EsphomeError
|
||||
import esphome.core.config as core_config
|
||||
|
||||
# `esphome.core.config` is imported lazily at its two use sites below.
|
||||
# It pulls in `esphome.automation` and `esphome.config_validation`, which
|
||||
# dominate `esphome.__main__` startup cost when loaded eagerly here.
|
||||
import esphome.final_validate as fv
|
||||
from esphome.helpers import indent
|
||||
from esphome.loader import ComponentManifest, get_component, get_platform
|
||||
@@ -968,6 +971,8 @@ class CoreFinalValidateStep(ConfigValidationStep):
|
||||
if result.errors:
|
||||
return
|
||||
|
||||
import esphome.core.config as core_config
|
||||
|
||||
token = fv.full_config.set(result)
|
||||
with result.catch_error([CONF_ESPHOME]):
|
||||
if CONF_ESPHOME in result:
|
||||
@@ -1072,6 +1077,8 @@ def validate_config(
|
||||
return result
|
||||
|
||||
# 2. Load partial core config
|
||||
import esphome.core.config as core_config
|
||||
|
||||
result[CONF_ESPHOME] = config[CONF_ESPHOME]
|
||||
result.add_output_path([CONF_ESPHOME], CONF_ESPHOME)
|
||||
try:
|
||||
|
||||
+12
-2
@@ -13,9 +13,13 @@ from typing import Any
|
||||
|
||||
from esphome.const import SOURCE_FILE_EXTENSIONS
|
||||
from esphome.core import CORE
|
||||
import esphome.core.config
|
||||
from esphome.types import ConfigType
|
||||
|
||||
# `esphome.core.config` is imported lazily in `_lookup_module` when the
|
||||
# "esphome" pseudo-component is first resolved. It pulls in
|
||||
# `esphome.automation` and `esphome.config_validation`, which together
|
||||
# dominate `esphome.__main__` startup cost when loaded eagerly.
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -202,6 +206,13 @@ def _lookup_module(domain: str, exception: bool) -> ComponentManifest | None:
|
||||
if domain in _COMPONENT_CACHE:
|
||||
return _COMPONENT_CACHE[domain]
|
||||
|
||||
if domain == "esphome":
|
||||
import esphome.core.config
|
||||
|
||||
manif = ComponentManifest(esphome.core.config)
|
||||
_COMPONENT_CACHE[domain] = manif
|
||||
return manif
|
||||
|
||||
try:
|
||||
module = importlib.import_module(f"esphome.components.{domain}")
|
||||
except ImportError as e:
|
||||
@@ -237,7 +248,6 @@ def get_platform(domain: str, platform: str) -> ComponentManifest | None:
|
||||
|
||||
_COMPONENT_CACHE: dict[str, ComponentManifest] = {}
|
||||
CORE_COMPONENTS_PATH = (Path(__file__).parent / "components").resolve()
|
||||
_COMPONENT_CACHE["esphome"] = ComponentManifest(esphome.core.config)
|
||||
|
||||
|
||||
def _replace_component_manifest(domain: str, manifest: ComponentManifest) -> None:
|
||||
|
||||
Reference in New Issue
Block a user