Add sync_debug_check_bounds_() that syncs pos_ from a local pointer
before checking bounds. Use it in encode_varint_raw_64 and
encode_varint_raw_slow_ to restore per-byte bounds checking in
debug mode without breaking the __restrict__ optimization in
production (where it's a no-op).
Previously encode_string called encode_varint_raw(len) then
encode_raw(data, len) as separate methods, each with their own
__restrict__ pos scope. This caused a redundant store-load pair
of pos_ between the two operations.
Inline the length varint write and memcpy under a single local
pos variable so the compiler can keep pos_ in a register across
both operations. Eliminates one load-store pair per string encode.
Apply the same __restrict__ local pointer pattern proven in
encode_varint_raw_64 to all remaining methods that write through
pos_: encode_varint_raw, encode_varint_raw_short, write_raw_byte,
encode_raw, write_tag_and_fixed32, encode_string, encode_bool,
and encode_fixed32.
Each method now hoists pos_ into a __restrict__ local before
writing and stores back once at the end. When the compiler inlines
these into a generated encode() method, it can keep pos_ in a
register across consecutive calls instead of reloading from memory
after every write.
Same optimization as encode_varint_raw_64: hoist pos_ into a
__restrict__ local so the compiler keeps it in a register across
the loop instead of reloading from memory each iteration.
Use a __restrict__ local pointer for the varint write loop so the
compiler can keep it in a register instead of reloading pos_ from
memory on each iteration. Eliminates the store→load dependency
chain that was causing 7 load/store pairs for a typical 48-bit
BLE address varint.
Use a __restrict__ local pointer for the varint write loop so the
compiler can keep it in a register instead of reloading pos_ from
memory on each iteration. Eliminates the store→load dependency
chain that was causing 7 load/store pairs for a typical 48-bit
BLE address varint.
Add encode_varint_raw_short() and ProtoSize::varint_short() that
inline both the 1-byte and 2-byte varint paths, falling back to
the noinline slow path for 3+ bytes.
Use these for sint32 fields (zigzag encoding), where values like
RSSI (-100 to 0) produce zigzag values that are 1-2 bytes. This
avoids a function call for the common case without bloating the
generic encode_varint_raw fast path.
Add CodSpeed benchmarks for BluetoothLERawAdvertisementsResponse
(12 advertisements) covering calculate_size, encode, calc+encode,
and fresh-buffer paths.
Includes a lightweight bluetooth_proxy stub header in
tests/benchmarks/stubs/ so the api component can compile with
USE_BLUETOOTH_PROXY on the host platform without pulling in
ESP32 BLE dependencies.
Remove direct include of build_info_data.h from version_text_sensor.cpp
and use the existing App.get_build_time_string() API instead. This
eliminates duplicate ESPHOME_BUILD_TIME_STR and ESPHOME_COMMENT_STR
symbols that were emitted into every translation unit including the
header (static const in a header = one copy per TU).
Now only application.cpp includes build_info_data.h, which also
improves incremental rebuild times: when build info changes, only
application.cpp needs recompiling instead of both application.cpp
and version_text_sensor.cpp.
Save 4 bytes per ActionList instance by removing the tail pointer
used only during setup() for O(1) append. Instead, walk the short
chain (typically 1-5 actions) to find the tail.
This saves 4 bytes per Automation on 32-bit platforms, which adds
up on memory-constrained devices like ESP8266 with many automations.
Template AndCondition, OrCondition, and XorCondition on N so the
condition pointer list is stored in std::array<Condition<Ts...>*, N>
instead of FixedVector. N is set by code generation to match the
exact number of conditions configured in YAML.
Add init_array_from() helper for optimal codegen when initializing
std::array from initializer_list.
Template ValueListFilter, FilterOutValueFilter, and ThrottleWithPriorityFilter
on N (the number of configured values) so the value list is stored in
std::array<TemplatableValue<float>, N> instead of FixedVector.
Non-template helpers value_list_matches_any() and throttle_check_and_update()
keep the iteration loops in the .cpp to avoid template bloat.
Forward declaration fails when filter.h is included before application.h
(incomplete type error). Instead, extract the throttle time check into a
non-template helper in filter.cpp that accesses App directly. This keeps
the same call overhead as the old ThrottleFilter (one function call) but
the helper does the time check AND updates last_input, so the template
new_value() body has no App dependency at all.