@@ -88,28 +88,31 @@ void SoundLevelMeter::setup() {
8888}
8989
9090void SoundLevelMeter::loop () {
91- if (!this ->defer_queue_ .empty ()) {
91+ // Process no more than 5 items per loop iteration.
92+ // When there are many sensors with short update intervals,
93+ // a large number of state updates (publish_state) may be queued.
94+ // Publishing state is a relatively expensive operation, so calling
95+ // it more than 10–20 times per iteration could trigger a warning
96+ // that the component is taking too long to operate. Therefore, we
97+ // limit the number of updates per iteration. The loop runs approximately
98+ // 100 times per second, so any remaining items will be processed
99+ // in the next iteration. Processing only one item per iteration is too
100+ // restrictive, as in extreme cases with many updates - say,
101+ // 100 per second - we might hit performance limits. Thus, we set a maximum
102+ // of 5 items per iteration, allowing up to 500 sensor updates per second
103+ // in theory, which should be more than sufficient for most scenarios.
104+ std::vector<std::function<void ()>> tasks;
105+ {
106+ uint32_t max_items = 5 ;
92107 std::lock_guard<std::mutex> lock (this ->defer_mutex_ );
93- // Process no more than 5 items per loop iteration.
94- // When there are many sensors with short update intervals,
95- // a large number of state updates (publish_state) may be queued.
96- // Publishing state is a relatively expensive operation, so calling
97- // it more than 10–20 times per iteration could trigger a warning
98- // that the component is taking too long to operate. Therefore, we
99- // limit the number of updates per iteration. The loop runs approximately
100- // 100 times per second, so any remaining items will be processed
101- // in the next iteration. Processing only one item per iteration is too
102- // restrictive, as in extreme cases with many updates - say,
103- // 100 per second - we might hit performance limits. Thus, we set a maximum
104- // of 5 items per iteration, allowing up to 500 sensor updates per second
105- // in theory, which should be more than sufficient for most scenarios.
106- uint32_t max_items = std::min (this ->defer_queue_ .size (), (size_t ) 5 );
107- for (int i = 0 ; i < max_items; i++) {
108- auto &f = this ->defer_queue_ .front ();
109- f ();
108+ for (int i = 0 ; i < max_items && !this ->defer_queue_ .empty (); i++) {
109+ tasks.push_back (std::move (this ->defer_queue_ .front ()));
110110 this ->defer_queue_ .pop_front ();
111111 }
112112 }
113+ for (auto &f : tasks) {
114+ f ();
115+ }
113116}
114117
115118void SoundLevelMeter::start () {
0 commit comments