This commit is contained in:
J. Nick Koston 2025-07-02 09:02:06 -05:00
parent dd49d832c4
commit ba5bb9dfa7
No known key found for this signature in database
2 changed files with 35 additions and 3 deletions

View File

@ -926,6 +926,7 @@ class MemoryAnalyzer:
elf_path: str, elf_path: str,
objdump_path: str | None = None, objdump_path: str | None = None,
readelf_path: str | None = None, readelf_path: str | None = None,
external_components: set[str] | None = None,
): ):
self.elf_path = Path(elf_path) self.elf_path = Path(elf_path)
if not self.elf_path.exists(): if not self.elf_path.exists():
@ -933,6 +934,7 @@ class MemoryAnalyzer:
self.objdump_path = objdump_path or "objdump" self.objdump_path = objdump_path or "objdump"
self.readelf_path = readelf_path or "readelf" self.readelf_path = readelf_path or "readelf"
self.external_components = external_components or set()
self.sections: dict[str, MemorySection] = {} self.sections: dict[str, MemorySection] = {}
self.components: dict[str, ComponentMemory] = defaultdict( self.components: dict[str, ComponentMemory] = defaultdict(
@ -1120,10 +1122,14 @@ class MemoryAnalyzer:
# Strip trailing underscore if present (e.g., switch_ -> switch) # Strip trailing underscore if present (e.g., switch_ -> switch)
component_name = component_name.rstrip("_") component_name = component_name.rstrip("_")
# Check if this is an actual component or core # Check if this is an actual component in the components directory
if component_name in ESPHOME_COMPONENTS: if component_name in ESPHOME_COMPONENTS:
return f"[esphome]{component_name}" return f"[esphome]{component_name}"
# Check if this is a known external component from the config
elif component_name in self.external_components:
return f"[external]{component_name}"
else: else:
# Everything else in esphome:: namespace is core
return "[esphome]core" return "[esphome]core"
# Check for esphome core namespace (no component namespace) # Check for esphome core namespace (no component namespace)
@ -1501,9 +1507,10 @@ def analyze_elf(
objdump_path: str | None = None, objdump_path: str | None = None,
readelf_path: str | None = None, readelf_path: str | None = None,
detailed: bool = False, detailed: bool = False,
external_components: set[str] | None = None,
) -> str: ) -> str:
"""Analyze an ELF file and return a memory report.""" """Analyze an ELF file and return a memory report."""
analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path) analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path, external_components)
analyzer.analyze() analyzer.analyze()
return analyzer.generate_report(detailed) return analyzer.generate_report(detailed)

View File

@ -389,8 +389,33 @@ def analyze_memory_usage(config: dict[str, Any]) -> None:
_LOGGER.warning("ELF file not found at %s or %s", elf_path, alt_path) _LOGGER.warning("ELF file not found at %s or %s", elf_path, alt_path)
return return
# Extract external components from config
external_components = set()
# Get the list of built-in ESPHome components
from esphome.analyze_memory import get_esphome_components
builtin_components = get_esphome_components()
# Special non-component keys that appear in configs
NON_COMPONENT_KEYS = {
CONF_ESPHOME,
"substitutions",
"packages",
"globals",
"<<",
}
# Check all top-level keys in config
for key in config:
if key not in builtin_components and key not in NON_COMPONENT_KEYS:
# This is an external component
external_components.add(key)
_LOGGER.debug("Detected external components: %s", external_components)
# Create analyzer and run analysis # Create analyzer and run analysis
analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path) analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path, external_components)
analyzer.analyze() analyzer.analyze()
# Generate and print report # Generate and print report