Extract the keepalive ping/disconnect cold path into a separate
noinline check_keepalive_() method. This code only fires once per
minute but was contributing ~110 bytes to the hot loop() body that
runs every ~16ms.
Results on ESP32 (xtensa):
- loop(): 374 → 263 bytes (-111 bytes, -30%)
- check_keepalive_(): 136 bytes (new, cold path)
- Net: +25 bytes total (call overhead), but the hot path icache
footprint is significantly reduced.
The template wrapper caused the compiler to make different
optimization decisions on setup(), negating the savings.
Calling register_component_ directly was -4 bytes.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Using the original register_component name (just moved to protected)
produces identical compiled output to the baseline, avoiding the
symbol name length overhead from renaming.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Rename the non-template to register_component_impl_ and add
a protected template register_component_ that wraps it. This
preserves the compiler optimization behavior (isra clones)
while keeping the method inaccessible to external components.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Without the template wrapper, the compiler inlines the 24-byte
function at each of ~92 call sites in setup(), growing setup()
by ~284 bytes. Force a function call instead.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Arduino.h on ESP8266 already declares void setup(void), so our
forward declaration triggers readability-redundant-declaration.
Co-Authored-By: J. Nick Koston <nick@koston.org>
The cpp test framework renames setup() to original_setup() and
replaces setup() with the gtest runner, so we need to friend both.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Instead of runtime null, duplicate, and capacity checks in
register_component_, make the method unreachable from outside
codegen by removing the public template wrapper and granting
friend access to the codegen-generated ::setup() function.
Since ESPHOME_COMPONENT_COUNT is set to exactly
len(CORE.component_ids) at codegen time, the StaticVector is
always correctly sized and the runtime capacity check cannot
trigger from codegen. External components that bypassed codegen
to call App.register_component() directly will now get a
compile error, forcing them to properly declare their components
in their config schema.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Move set_component_state_ from component.cpp to the header as
an inline method so it can be reused wherever Component state
needs to be updated. Replace the manual bit manipulation in
Application::enable_pending_loops_ with a call to the helper.
Co-Authored-By: J. Nick Koston <nick@koston.org>
The sen6x test YAML used identical sensor IDs (pm_1_0, pm_2_5,
pm_4_0, pm_10_0) as sen5x, causing ID redefinition errors when
both components are tested together in grouped builds. Prefix
the sen6x IDs with sen6x_ to make them unique.
Make set_mode(const char*, size_t) the real implementation using
ESPHOME_strncasecmp_P with length checks, instead of ignoring len
and delegating to the null-terminated overload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Avoid implicit StringRef->std::string conversion when the protobuf
message fields are already StringRef. Use the (const char*, size_t)
overloads directly.