Merge remote-tracking branch 'upstream/dev' into integration

This commit is contained in:
J. Nick Koston
2026-03-25 08:47:35 -10:00
33 changed files with 288 additions and 120 deletions
@@ -0,0 +1,79 @@
#include <benchmark/benchmark.h>
#include "esphome/components/sensor/sensor.h"
namespace esphome::benchmarks {
// Inner iteration count to amortize CodSpeed instrumentation overhead.
// Without this, the ~60ns per-iteration valgrind start/stop cost dominates
// sub-microsecond benchmarks.
static constexpr int kInnerIterations = 2000;
// Test subclass to access protected configure_entity_() for benchmark setup.
class TestSensor : public sensor::Sensor {
public:
void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); }
};
// --- Sensor::publish_state() with no callbacks registered ---
// Measures baseline publish overhead: state assignment, logging,
// internal_send_state_to_frontend, ControllerRegistry notification.
static void SensorPublish_NoCallbacks(benchmark::State &state) {
TestSensor sensor;
sensor.configure("test_sensor");
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
sensor.publish_state(static_cast<float>(i));
}
benchmark::DoNotOptimize(sensor.state);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(SensorPublish_NoCallbacks);
// --- Sensor::publish_state() with one state callback ---
// Measures callback dispatch overhead through LazyCallbackManager.
static void SensorPublish_WithCallback(benchmark::State &state) {
TestSensor sensor;
sensor.configure("test_sensor");
float callback_value = 0.0f;
sensor.add_on_state_callback([&callback_value](float value) { callback_value = value; });
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
sensor.publish_state(static_cast<float>(i));
}
benchmark::DoNotOptimize(callback_value);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(SensorPublish_WithCallback);
// --- Sensor::publish_state() with the same value every time ---
// Steady-state pattern: sensor reports an unchanged reading.
// Sensor doesn't dedup today, so this exercises the same code path
// as changing values, but tracks the common real-world pattern
// separately for regression detection.
static void SensorPublish_SameValue(benchmark::State &state) {
TestSensor sensor;
sensor.configure("test_sensor");
// Warm up so has_state is already set
sensor.publish_state(23.5f);
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
sensor.publish_state(23.5f);
}
benchmark::DoNotOptimize(sensor.state);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(SensorPublish_SameValue);
} // namespace esphome::benchmarks
+11 -20
View File
@@ -43,9 +43,6 @@ lvgl:
start_value: 0
end_value: 180
bg_color: light_blue
disp_bg_color: color_id
disp_bg_image: cat_image
disp_bg_opa: cover
bottom_layer:
widgets:
- obj:
@@ -58,7 +55,6 @@ lvgl:
gradients:
- id: color_bar
direction: hor
# dither: err_diff
stops:
- color: 0xFF0000
position: 0
@@ -143,12 +139,11 @@ lvgl:
body:
text: This is a sample messagebox
bg_color: 0x808080
button_style:
bg_color: 0xff00
border_width: 4
buttons:
- id: msgbox_button
text: Button
bg_color: 0x00ff00
border_width: 4
- id: msgbox_apply
text: "Close"
on_click:
@@ -160,8 +155,8 @@ lvgl:
bg_opa: !lambda return 0.5;
- lvgl.image.update:
id: lv_image
zoom: !lambda return 512;
angle: !lambda return 100;
scale: !lambda return 512;
rotation: !lambda return 100;
pivot_x: !lambda return 20;
pivot_y: !lambda return 20;
offset_x: !lambda return 20;
@@ -287,8 +282,8 @@ lvgl:
then:
- lvgl.animimg.stop: anim_img
- lvgl.update:
disp_bg_color: 0xffff00
disp_bg_image: none
bottom_layer:
bg_color: 0xffff00
- lvgl.widget.show: message_box
- label:
text: "Hello shiny day"
@@ -361,8 +356,6 @@ lvgl:
pad_right: 10px
pad_top: 10px
shadow_color: light_blue
shadow_ofs_x: 5
shadow_ofs_y: 5
shadow_opa: cover
shadow_spread: 5
shadow_width: 10
@@ -373,12 +366,10 @@ lvgl:
text_letter_space: 4
text_line_space: 4
text_opa: cover
transform_angle: 180
transform_rotation: 90
transform_height: 100
transform_pivot_x: 50%
transform_pivot_y: 50%
transform_zoom: 0.5
transform_scale: 2.0
transform_scale_x: 1.5
transform_scale_y: 0.8
@@ -470,11 +461,11 @@ lvgl:
id: button_button
width: 20%
height: 10%
transform_angle: !lambda return(180*100);
transform_rotation: !lambda return(180*100);
arc_width: !lambda return 4;
border_width: !lambda return 6;
shadow_ofs_x: !lambda return 6;
shadow_ofs_y: !lambda return 6;
shadow_offset_x: !lambda return 6;
shadow_offset_y: !lambda return 6;
shadow_spread: !lambda return 6;
shadow_width: !lambda return 6;
pressed:
@@ -646,8 +637,8 @@ lvgl:
border_opa: 80%
shadow_color: black
shadow_width: 10
shadow_ofs_x: 5
shadow_ofs_y: 5
shadow_offset_x: 5
shadow_offset_y: 5
shadow_spread: 4
shadow_opa: cover
outline_color: red
+30 -17
View File
@@ -273,26 +273,39 @@ text_sensor:
display:
- platform: nextion
id: main_lcd
auto_wake_on_touch: true
brightness: 80%
command_spacing: 5ms
dump_device_info: true
exit_reparse_on_start: true
lambda: |-
ESP_LOGD("display","Display is being tested!");
max_commands_per_loop: 20
max_queue_age: 5000ms # Remove queue items after 5s
max_queue_size: 50
update_interval: 5s
on_sleep:
then:
lambda: 'ESP_LOGD("display","Display went to sleep");'
on_wake:
then:
lambda: 'ESP_LOGD("display","Display woke up");'
on_setup:
then:
lambda: 'ESP_LOGD("display","Display setup completed");'
on_page:
then:
lambda: 'ESP_LOGD("display","Display shows new page %u", x);'
on_buffer_overflow:
then:
logger.log: "Nextion reported a buffer overflow!"
command_spacing: 5ms
dump_device_info: true
max_queue_age: 5000ms # Remove queue items after 5s
on_page:
then:
lambda: 'ESP_LOGD("display","Display shows new page %u", x);'
on_setup:
then:
lambda: 'ESP_LOGD("display","Display setup completed");'
on_sleep:
then:
lambda: 'ESP_LOGD("display","Display went to sleep");'
on_touch:
then:
lambda: |-
ESP_LOGD("display",
"Display was touched at page %u, component %u, touch event: %s",
page_id, component_id, touch_event ? "press" : "release");
on_wake:
then:
lambda: 'ESP_LOGD("display","Display woke up");'
update_interval: 5s
start_up_page: 1
startup_override_ms: 10000ms # Wait 10s for display ready
touch_sleep_timeout: 3
wake_up_page: 2