mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Reduce logger CPU usage by disabling loop when buffer is empty
This commit is contained in:
		| @@ -48,6 +48,11 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char * | |||||||
|   // For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered |   // For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered | ||||||
|   message_sent = this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag, |   message_sent = this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag, | ||||||
|                                                              static_cast<uint16_t>(line), current_task, format, args); |                                                              static_cast<uint16_t>(line), current_task, format, args); | ||||||
|  |   if (message_sent) { | ||||||
|  |     // Enable logger loop to process the buffered message | ||||||
|  |     // This is safe to call from any context including ISRs | ||||||
|  |     this->enable_loop_soon_any_context(); | ||||||
|  |   } | ||||||
| #endif  // USE_ESPHOME_TASK_LOG_BUFFER | #endif  // USE_ESPHOME_TASK_LOG_BUFFER | ||||||
|  |  | ||||||
|   // Emergency console logging for non-main tasks when ring buffer is full or disabled |   // Emergency console logging for non-main tasks when ring buffer is full or disabled | ||||||
| @@ -139,10 +144,14 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate | |||||||
| #ifdef USE_ESPHOME_TASK_LOG_BUFFER | #ifdef USE_ESPHOME_TASK_LOG_BUFFER | ||||||
| void Logger::init_log_buffer(size_t total_buffer_size) { | void Logger::init_log_buffer(size_t total_buffer_size) { | ||||||
|   this->log_buffer_ = esphome::make_unique<logger::TaskLogBuffer>(total_buffer_size); |   this->log_buffer_ = esphome::make_unique<logger::TaskLogBuffer>(total_buffer_size); | ||||||
|  |  | ||||||
|  |   // Start with loop disabled when using task buffer (unless using USB CDC) | ||||||
|  |   // The loop will be enabled automatically when messages arrive | ||||||
|  |   this->disable_loop_when_buffer_empty_(); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32) | #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESPHOME_TASK_LOG_BUFFER) | ||||||
| void Logger::loop() { | void Logger::loop() { | ||||||
| #if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO) | #if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO) | ||||||
|   if (this->uart_ == UART_SELECTION_USB_CDC) { |   if (this->uart_ == UART_SELECTION_USB_CDC) { | ||||||
| @@ -189,6 +198,10 @@ void Logger::loop() { | |||||||
|         this->write_msg_(this->tx_buffer_); |         this->write_msg_(this->tx_buffer_); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } else { | ||||||
|  |     // No messages to process, disable loop if appropriate | ||||||
|  |     // This reduces overhead when there's no async logging activity | ||||||
|  |     this->disable_loop_when_buffer_empty_(); | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|   | |||||||
| @@ -107,7 +107,7 @@ class Logger : public Component { | |||||||
| #ifdef USE_ESPHOME_TASK_LOG_BUFFER | #ifdef USE_ESPHOME_TASK_LOG_BUFFER | ||||||
|   void init_log_buffer(size_t total_buffer_size); |   void init_log_buffer(size_t total_buffer_size); | ||||||
| #endif | #endif | ||||||
| #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32) | #if defined(USE_LOGGER_USB_CDC) || defined(USE_ESPHOME_TASK_LOG_BUFFER) | ||||||
|   void loop() override; |   void loop() override; | ||||||
| #endif | #endif | ||||||
|   /// Manually set the baud rate for serial, set to 0 to disable. |   /// Manually set the baud rate for serial, set to 0 to disable. | ||||||
| @@ -347,6 +347,26 @@ class Logger : public Component { | |||||||
|     static const int RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR); |     static const int RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR); | ||||||
|     this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size); |     this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #ifdef USE_ESPHOME_TASK_LOG_BUFFER | ||||||
|  |   // Disable loop when task buffer is empty (with USB CDC check) | ||||||
|  |   inline void disable_loop_when_buffer_empty_() { | ||||||
|  |     // Thread safety note: This is safe even if another task calls enable_loop_soon_any_context() | ||||||
|  |     // concurrently. If that happens between our check and disable_loop(), the enable request | ||||||
|  |     // will be processed on the next main loop iteration since: | ||||||
|  |     // - disable_loop() takes effect immediately | ||||||
|  |     // - enable_loop_soon_any_context() sets a pending flag that's checked at loop start | ||||||
|  | #if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO) | ||||||
|  |     // Only disable if not using USB CDC (which needs loop for connection detection) | ||||||
|  |     if (this->uart_ != UART_SELECTION_USB_CDC) { | ||||||
|  |       this->disable_loop(); | ||||||
|  |     } | ||||||
|  | #else | ||||||
|  |     // No USB CDC support, always safe to disable | ||||||
|  |     this->disable_loop(); | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| extern Logger *global_logger;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | extern Logger *global_logger;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user