Both messages are unconditionally exercised in the proxy hot paths
(every Z-Wave frame received from the controller; every UART read on a
configured serial proxy), so the modest flash cost of forcing -O2 on
their encode/calculate_size pays off on every device that has the proxy
enabled. Same treatment as InfraredRFReceiveEvent in the prior commit
and the other high-volume server-emitted messages.
This message is emitted on every IR/RF receive event with a packed sint32
timings array (typically ~50-200 entries). The encode walks the vector
calling ProtoEncode::encode_sint32 per element; under -Os GCC does not
inline those helpers, so each element pays the call overhead.
Adding option (speed_optimized) = true to the proto definition causes
the codegen to emit __attribute__((optimize("O2"))) on encode and
calculate_size, matching what already exists on SensorStateResponse,
SubscribeLogsResponse, and BluetoothLERawAdvertisementsResponse — the
other high-volume server-emitted messages.
The CodSpeed Encode_InfraredRFReceiveEvent / CalculateSize_InfraredRFReceiveEvent
benchmarks added in the parent PR will quantify the improvement.
- Make UARTFlushResult in the serial_proxy stub a scoped enum class with
matching scoped enumerator return in flush_port(), so the stub
signature lines up with the real esphome::uart::UARTFlushResult.
- Replace heap-leaking lazy-init in get_ir_timings_100() with a
function-local static const std::vector populated by a regular helper
function. Same lazy-init behavior, no leak in valgrind/ASan, no lambda
IIFE.
- Emit field 6 (modulation = 1) in build_infrared_rf_transmit_wire() so
the bytes match the documented field list and the decode benchmark
also exercises the field-6 decode_varint path.
Simplifies the decode benchmarks to mirror the encode pattern more
closely: no per-iteration asm volatile barrier, no return-by-value of
APIBuffer through encode_message_for_proxy. CodSpeed callgrind has been
crashing inside Decode_ZWaveProxyFrame and the previous setup was the
main thing it had that the (passing) Encode_ZWaveProxyFrame did not.
Splitting these out from bench_proto_encode.cpp and bench_proto_decode.cpp
moves them to the end of the linker's static-init order. CodSpeed's
callgrind runner has been segfaulting immediately after measuring the
last existing decode benchmark (Decode_SwitchCommandRequest), and
isolating the new code into its own translation unit lets us see whether
the crash is triggered by one of the new benchmarks or by something
about the new USE_*_PROXY/USE_INFRARED/USE_RADIO_FREQUENCY defines
changing how api_pb2.cpp compiles.
The InfraredRFReceiveEvent encode benchmark used a C++17 lambda IIFE
(`[]{...}()`) to seed a function-static vector, and the
InfraredRFTransmitRawTimingsRequest decode benchmark grew its APIBuffer
one byte at a time (~210 grow_() calls), each allocating a fresh
exact-fit buffer and memcpy'ing the prior contents. Both patterns are
fine under direct execution but appear to hit a CodSpeed/valgrind
edge case during the simulated benchmark run.
Switch to a plain heap-init pattern for the vector and build the wire
bytes into a stack array first, then resize+memcpy into the APIBuffer
once.
Mirrors the existing BluetoothLERawAdvertisementsResponse benchmarks for
the remaining proxy message families: ZWaveProxyFrame/ZWaveProxyRequest,
SerialProxyDataReceived/SerialProxyWriteRequest, and
InfraredRFReceiveEvent/InfraredRFTransmitRawTimingsRequest.
Adds minimal stub headers under tests/benchmarks/stubs/ for the
zwave_proxy, infrared, radio_frequency, and serial_proxy components so
api_connection.cpp compiles without dragging in their UART/RMT/BLE
hardware dependencies.
Followup to #16129. DelayAction now keys its scheduler entry by
self-pointer (NameType::SELF_POINTER), so the DELAY_ACTION enum
value is no longer referenced anywhere.
Self-keyed scheduler items (Scheduler::set_timeout(self, ...) and
set_interval(self, ...)) intentionally store component == nullptr. When
USE_RUNTIME_STATS is enabled, WarnIfComponentBlockingGuard::finish()
dereferenced component_ to call runtime_stats_.record_time(), causing a
load access fault on RISC-V (e.g. ESP32-C3) when these timers fire.
Skip the per-component bookkeeping when component_ is null, but still
accumulate into ComponentRuntimeStats::global_recorded_us so
Application::loop() overhead accounting (which subtracts scheduled
callback time from before_loop_tasks_) stays accurate.
- hal.cpp: include esphome/core/helpers.h for the HOT macro (millis/delay
use it; without the include the TU fails to compile).
- hal_esp8266.h: drop the redundant arch_get_cpu_cycle_count() bare
declaration that came back via the merge from dev (the inline def
above already declares the function).