mirror of
https://github.com/esphome/esphome.git
synced 2026-09-24 05:24:14 +00:00
[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
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "esphome/components/api/api_pb2.h"
|
||||
#include "esphome/components/api/api_buffer.h"
|
||||
|
||||
namespace esphome::api::benchmarks {
|
||||
|
||||
// --- HelloRequest decode (string + varint fields) ---
|
||||
|
||||
static void BM_Decode_HelloRequest(benchmark::State &state) {
|
||||
// Manually encoded HelloRequest:
|
||||
// field 1 (string): "aioesphomeapi"
|
||||
// field 2 (varint): 1 (api_version_major)
|
||||
// field 3 (varint): 10 (api_version_minor)
|
||||
uint8_t encoded[] = {
|
||||
0x0A, 0x0D, // field 1, length 13
|
||||
'a', 'i', 'o', 'e', 's', 'p', 'h', 'o', 'm', 'e', 'a', 'p', 'i', // "aioesphomeapi"
|
||||
0x10, 0x01, // field 2, value 1
|
||||
0x18, 0x0A, // field 3, value 10
|
||||
};
|
||||
|
||||
for (auto _ : state) {
|
||||
HelloRequest msg;
|
||||
msg.decode(encoded, sizeof(encoded));
|
||||
benchmark::DoNotOptimize(msg.api_version_major);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Decode_HelloRequest);
|
||||
|
||||
// --- SwitchCommandRequest decode (simple command) ---
|
||||
|
||||
static void BM_Decode_SwitchCommandRequest(benchmark::State &state) {
|
||||
// field 1 (fixed32): key = 0x12345678
|
||||
// field 2 (varint): state = true
|
||||
uint8_t encoded[] = {
|
||||
0x0D, 0x78, 0x56, 0x34, 0x12, // field 1, fixed32
|
||||
0x10, 0x01, // field 2, varint true
|
||||
};
|
||||
|
||||
for (auto _ : state) {
|
||||
SwitchCommandRequest msg;
|
||||
msg.decode(encoded, sizeof(encoded));
|
||||
benchmark::DoNotOptimize(msg.state);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Decode_SwitchCommandRequest);
|
||||
|
||||
// --- LightCommandRequest decode (complex command with many fields) ---
|
||||
|
||||
static void BM_Decode_LightCommandRequest(benchmark::State &state) {
|
||||
uint8_t encoded[] = {
|
||||
// field 1: key (fixed32) = 0x11223344
|
||||
0x0D,
|
||||
0x44,
|
||||
0x33,
|
||||
0x22,
|
||||
0x11,
|
||||
// field 2: has_state (varint) = true
|
||||
0x10,
|
||||
0x01,
|
||||
// field 3: state (varint) = true
|
||||
0x18,
|
||||
0x01,
|
||||
// field 4: has_brightness (varint) = true
|
||||
0x20,
|
||||
0x01,
|
||||
// field 5: brightness (fixed32/float) = 0.8
|
||||
0x2D,
|
||||
0xCD,
|
||||
0xCC,
|
||||
0x4C,
|
||||
0x3F,
|
||||
// field 9: has_rgb (varint) = true
|
||||
0x48,
|
||||
0x01,
|
||||
// field 10: red (fixed32/float) = 1.0
|
||||
0x55,
|
||||
0x00,
|
||||
0x00,
|
||||
0x80,
|
||||
0x3F,
|
||||
// field 11: green (fixed32/float) = 0.5
|
||||
0x5D,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x3F,
|
||||
// field 12: blue (fixed32/float) = 0.2
|
||||
0x65,
|
||||
0xCD,
|
||||
0xCC,
|
||||
0x4C,
|
||||
0x3E,
|
||||
// field 20: has_effect (varint) = true
|
||||
0xA0,
|
||||
0x01,
|
||||
0x01,
|
||||
// field 21: effect (string) = "rainbow"
|
||||
0xAA,
|
||||
0x01,
|
||||
0x07,
|
||||
'r',
|
||||
'a',
|
||||
'i',
|
||||
'n',
|
||||
'b',
|
||||
'o',
|
||||
'w',
|
||||
};
|
||||
|
||||
for (auto _ : state) {
|
||||
LightCommandRequest msg;
|
||||
msg.decode(encoded, sizeof(encoded));
|
||||
benchmark::DoNotOptimize(msg.brightness);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Decode_LightCommandRequest);
|
||||
|
||||
} // namespace esphome::api::benchmarks
|
||||
Reference in New Issue
Block a user