Skip to content

Commit 01c712b

Browse files
committed
reduce locking duration
1 parent 3c42a5d commit 01c712b

1 file changed

Lines changed: 21 additions & 18 deletions

File tree

components/sound_level_meter/sound_level_meter.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,31 @@ void SoundLevelMeter::setup() {
8888
}
8989

9090
void 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

115118
void SoundLevelMeter::start() {

0 commit comments

Comments
 (0)