Move FreeRTOS Mutex methods inline into helpers.h, eliminating
duplicate out-of-line definitions in esp32/helpers.cpp and
libretiny/helpers.cpp.
Hot path impact (disassembled from ELF):
| Platform | Before | After | Saved |
|--------------------|----------|----------|---------|
| ESP32 (Xtensa) | 1304 B | 1270 B | -34 B |
| BK72xx (ARM M4) | 1400 B | 1396 B | -4 B |
| RTL87xx (ARM M33) | 1248 B | 1246 B | -2 B |
| ESP32-C3 (RISC-V) | 1498 B | 1494 B | -4 B |
GCC generates ISRA clones that hoist the handle_ load into callers
and use tail calls to xQueueSemaphoreTake/xQueueGenericSend.
The fast path (millis + subtract + compare) is tiny and called once
per component per loop iteration. Moving it inline eliminates a
call8/retw pair per component, reducing main loop overhead.
The cold warning path (warn_if_blocking) and runtime stats recording
remain out-of-line in component.cpp.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The fast path (millis + subtract + compare) is tiny and called once
per component per loop iteration. Moving it inline eliminates a
call8/retw pair per component, reducing main loop overhead.
The cold warning path (warn_if_blocking) and runtime stats recording
remain out-of-line in component.cpp.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add APIBuffer::reserve_and_resize() to eliminate duplicate grow_()
capacity checks when reserve() is immediately followed by resize().
This saves one grow_() check per call site (~12 bytes each).
Simplify set_nodelay_for_message() Nagle batching state machine by
replacing the NODELAY_ON (-1) sentinel with a simple counter starting
at 0. Reduces branches from 5 to 3 with identical behavior verified
by exhaustive testing of all 2^N message sequences up to length 12.
Saves 32 bytes flash on ESP8266.
ESP-IDF places log_format_text.c in IRAM/DRAM via linker fragment
(noflash) when CONFIG_LOG_IN_IRAM=y. Our override is in a different
compilation unit so string literals would default to flash. In
constrained environments where flash cache is disabled, reading
flash-resident format strings would fault.
Move all format string constants to DRAM_ATTR to match ESP-IDF's
own behavior.
Switch from ESP-IDF Log V1 to V2, which centralizes log formatting
inside esp_log() instead of expanding esp_log_timestamp(), color codes,
and LOG_FORMAT() at every ESP_LOGx macro call site.
This saves ~9KB of flash by eliminating ~500 per-site macro expansions
in ESP-IDF library code (gpio, ethernet, mdns, uart, wifi, etc.).
Override esp_log_format() to skip ESP-IDF's own formatting after the
ESPHome logger hook is installed, since ESPHome does its own formatting.
For early boot and constrained environments (ISR, cache disabled),
format messages in ESPHome style with colors using a stack buffer.
LwIPLock was introduced for RP2040 WiFi in #14679 to prevent race
conditions between lwip callbacks and the main loop. However, on
platforms without lwIP core locking (ESP8266, LibreTiny, Zephyr,
RP2040 without WiFi), the constructor/destructor were empty stubs
in .cpp files that the compiler could not see through, generating
unnecessary function calls at every call site.
Move the no-op implementation inline into helpers.h so the compiler
can eliminate all LwIPLock overhead on these platforms. ESP32 and
RP2040+WiFi retain their out-of-line implementations with real
locking.
LwIPLock was introduced for RP2040 WiFi in #14679 to prevent race
conditions between lwip callbacks and the main loop. However, on
platforms without lwIP core locking (ESP8266, LibreTiny, Zephyr,
RP2040 without WiFi), the constructor/destructor were empty stubs
in .cpp files that the compiler could not see through, generating
unnecessary function calls at every call site.
Move the no-op implementation inline into helpers.h so the compiler
can eliminate all LwIPLock overhead on these platforms. ESP32 and
RP2040+WiFi retain their out-of-line implementations with real
locking.
Move get_name() and get_object_id_hash() definitions from
entity_base.cpp to entity_base.h so the compiler can inline
these trivial member accessors, eliminating call overhead at
every call site.