mirror of
https://github.com/esphome/esphome.git
synced 2026-09-21 03:58:41 +00:00
Use empty() instead of empty_relaxed() for wifi_loop_ fast path
GCC on Xtensa emits memw for relaxed atomic loads too, so the savings from relaxed vs acquire are only 2 memw (~4 cycles) — not worth the weaker correctness guarantees. The real optimization is the early return that skips get_and_reset_dropped_count() and the pop() loop entirely.
This commit is contained in:
@@ -716,9 +716,8 @@ const char *get_disconnect_reason_str(uint8_t reason) {
|
||||
}
|
||||
|
||||
void WiFiComponent::wifi_loop_() {
|
||||
// Fast path: relaxed check avoids acquire fences (4x memw on Xtensa) when queue is empty.
|
||||
// Safe from consumer side — worst case we process events one loop iteration late.
|
||||
if (this->event_queue_.empty_relaxed())
|
||||
// Fast path: skip dropped count check and pop loop when queue is empty
|
||||
if (this->event_queue_.empty())
|
||||
return;
|
||||
|
||||
uint16_t dropped = this->event_queue_.get_and_reset_dropped_count();
|
||||
|
||||
@@ -778,10 +778,8 @@ network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask(
|
||||
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; }
|
||||
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; }
|
||||
void WiFiComponent::wifi_loop_() {
|
||||
// Fast path: skip queue drain when empty.
|
||||
// On LockFreeQueue platforms, relaxed loads avoid memory fences.
|
||||
// On FreeRTOSQueue platforms, this is a lightweight uxQueueMessagesWaiting check.
|
||||
if (this->event_queue_.empty_relaxed())
|
||||
// Fast path: skip dropped count check and pop loop when queue is empty
|
||||
if (this->event_queue_.empty())
|
||||
return;
|
||||
|
||||
uint16_t dropped = this->event_queue_.get_and_reset_dropped_count();
|
||||
|
||||
@@ -82,10 +82,6 @@ template<class T, uint8_t SIZE> class FreeRTOSQueue {
|
||||
|
||||
bool empty() const { return uxQueueMessagesWaiting(this->handle_) == 0; }
|
||||
|
||||
/// Fast empty check — same as empty() for FreeRTOS queues since
|
||||
/// uxQueueMessagesWaiting is already a lightweight read.
|
||||
bool empty_relaxed() const { return this->empty(); }
|
||||
|
||||
bool full() const { return uxQueueSpacesAvailable(this->handle_) == 0; }
|
||||
|
||||
size_t size() const { return uxQueueMessagesWaiting(this->handle_); }
|
||||
|
||||
@@ -118,12 +118,6 @@ template<class T, uint8_t SIZE> class LockFreeQueue {
|
||||
|
||||
bool empty() const { return head_.load(std::memory_order_acquire) == tail_.load(std::memory_order_acquire); }
|
||||
|
||||
/// Fast empty check using relaxed loads — no memory fences on Xtensa.
|
||||
/// Safe when called only from the consumer side: head_ is only written by the
|
||||
/// consumer, and tail_ can only advance. Worst case we miss a just-pushed item
|
||||
/// and catch it next loop iteration.
|
||||
bool empty_relaxed() const { return head_.load(std::memory_order_relaxed) == tail_.load(std::memory_order_relaxed); }
|
||||
|
||||
bool full() const {
|
||||
uint8_t next_tail = next_index(tail_.load(std::memory_order_relaxed));
|
||||
return next_tail == head_.load(std::memory_order_acquire);
|
||||
|
||||
Reference in New Issue
Block a user