Files
esphome/tests/benchmarks/components/api/bench_application_loop.cpp
T
J. Nick Koston 38ff332fec [core] Add CodSpeed C++ benchmarks for protobuf and main loop
Add automated benchmarks using Google Benchmark to prevent performance
regressions in the API protobuf encoding/decoding and core loop paths.

Benchmarks cover:
- Protobuf encode: SensorState, BinarySensorState, HelloResponse,
  LightState, DeviceInfoResponse (20 nested devices + 20 areas)
- Protobuf decode: HelloRequest, SwitchCommand, LightCommand
- Protobuf calculate_size and full calc+encode send path
- Varint parse/encode/size for various value ranges
- Scheduler call/next_schedule_in with idle and active timers
- Application loop component dispatch and blocking guard overhead

Infrastructure:
- Extract shared build logic from cpp_unit_test.py into test_helpers.py
- Add cpp_benchmark.py mirroring the unit test build pattern
- Support benchmark.yaml per component dir for declaring dependencies
- Add CodSpeed CI workflow triggered on api/core changes
- Fix ProtoMessage protected destructor on host platform
2026-03-16 19:25:46 -10:00

51 lines
1.3 KiB
C++

#include <benchmark/benchmark.h>
#include "esphome/core/application.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
namespace esphome::benchmarks {
// A minimal component with an empty loop for benchmarking dispatch overhead
class NoopComponent : public Component {
public:
void loop() override {}
float get_setup_priority() const override { return 0.0f; }
// Expose protected method for benchmarking
void set_loop_state() { this->set_component_state_(COMPONENT_STATE_LOOP); }
};
// --- WarnIfComponentBlockingGuard overhead ---
static void BM_WarnIfComponentBlockingGuard(benchmark::State &state) {
NoopComponent component;
uint32_t now = millis();
for (auto _ : state) {
WarnIfComponentBlockingGuard guard{&component, now};
now = guard.finish();
benchmark::DoNotOptimize(now);
}
}
BENCHMARK(BM_WarnIfComponentBlockingGuard);
// --- Component virtual dispatch overhead ---
static void BM_ComponentDispatch(benchmark::State &state) {
NoopComponent component;
component.set_loop_state();
uint32_t now = millis();
for (auto _ : state) {
{
WarnIfComponentBlockingGuard guard{&component, now};
component.loop();
now = guard.finish();
}
benchmark::DoNotOptimize(now);
}
}
BENCHMARK(BM_ComponentDispatch);
} // namespace esphome::benchmarks