When an interval fires in Scheduler::call(), push it directly back into
items_ via push_back() + push_heap() instead of routing through the
to_add_ staging vector and process_to_add_slow_path_().
This eliminates per-cycle overhead of process_to_add_slow_path_() which
acquires a lock, iterates to_add_, pushes each item into the heap, clears
the vector, and resets the atomic counter.
Add cv.ByteLength() validator that checks UTF-8 byte length instead
of character count. This ensures multibyte characters don't cause
the encoded string to exceed the proto max_data_length limit.
Switch all length validators that feed into proto fields with
max_data_length annotations to use byte length:
- Entity names, friendly names, area names, device names
- Icons, device classes, units of measurement
- Board names, project name/version
- Fix HelloResponse.name and DeviceInfoResponse.name max_data_length
from 120 to 31 to match ESPHOME_DEVICE_NAME_MAX_LEN (hostname limit)
- Add max_data_length=120 + force to suggested_area field
- Add static_asserts for ESPHOME_DEVICE_NAME_MAX_LEN and
ESPHOME_FRIENDLY_NAME_MAX_LEN
- Fix comments to accurately describe guarantees
Add BOARD_MAX_LENGTH and PROJECT_MAX_LENGTH constants (127) and
enforce them in YAML validation for all platform board schemas
and project name/version.
Add max_data_length + force proto options to model, project_name,
and project_version fields in DeviceInfoResponse.
Add max_data_length + force proto options to string fields in
HelloResponse, AreaInfo, DeviceInfo, and DeviceInfoResponse where
we have strong compile-time or codegen guarantees on max length.
This enables encode_short_string_force() (direct byte writes,
no varint branching) for fields with single-byte tags, and
fixed-formula size calculations for all annotated fields.
Add static_asserts to cross-validate C++ constexpr constants
(MAC_ADDRESS_PRETTY_BUFFER_SIZE, BUILD_TIME_STR_SIZE,
ESPHOME_VERSION, ESPHOME_MANUFACTURER) against the proto
max_data_length annotations.
Move the notify_*_update() method definitions from controller_registry.cpp
into controller_registry.h as inline functions. These are tiny loops over
1-2 controllers that each have a single call site in the entity's
notify_frontend_() method.
When defined in a separate TU, the compiler cannot inline them at the call
site without LTO, resulting in an unnecessary function-call frame on every
state publish. CodSpeed profiling of the CallbackManager container change
(#15272) showed this extra frame accounting for ~12% regression in text
sensor publish benchmarks.
controller_registry.h is only ever included from .cpp files (never from
other headers), so including controller.h after the class definition is
safe and introduces no circular dependencies.