mirror of
https://github.com/esphome/esphome.git
synced 2026-09-16 01:28:39 +00:00
[logger] Reduce per-message overhead by inlining hot path helpers (#14851)
This commit is contained in:
@@ -111,7 +111,12 @@ struct LogBuffer {
|
||||
}
|
||||
#endif
|
||||
void write_body(const char *text, uint16_t text_length) {
|
||||
this->write_(text, text_length);
|
||||
const uint16_t available = this->remaining_();
|
||||
const uint16_t copy_len = (text_length < available) ? text_length : available;
|
||||
if (copy_len > 0) {
|
||||
memcpy(this->current_(), text, copy_len);
|
||||
this->pos += copy_len;
|
||||
}
|
||||
this->finalize_();
|
||||
}
|
||||
|
||||
@@ -119,21 +124,23 @@ struct LogBuffer {
|
||||
bool full_() const { return this->pos >= this->size; }
|
||||
uint16_t remaining_() const { return this->size - this->pos; }
|
||||
char *current_() { return this->data + this->pos; }
|
||||
void write_(const char *value, uint16_t length) {
|
||||
const uint16_t available = this->remaining_();
|
||||
const uint16_t copy_len = (length < available) ? length : available;
|
||||
if (copy_len > 0) {
|
||||
memcpy(this->current_(), value, copy_len);
|
||||
this->pos += copy_len;
|
||||
}
|
||||
}
|
||||
void finalize_() {
|
||||
// Write color reset sequence
|
||||
static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1;
|
||||
this->write_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN);
|
||||
this->write_ansi_reset_();
|
||||
// Null terminate
|
||||
this->data[this->full_() ? this->size - 1 : this->pos] = '\0';
|
||||
}
|
||||
// Write ANSI reset sequence inline ("\033[0m") - avoids write_() call overhead
|
||||
static constexpr uint16_t ANSI_RESET_LEN = 4; // "\033[0m"
|
||||
void write_ansi_reset_() {
|
||||
if (this->remaining_() >= ANSI_RESET_LEN) {
|
||||
char *p = this->current_();
|
||||
*p++ = '\033';
|
||||
*p++ = '[';
|
||||
*p++ = '0';
|
||||
*p++ = 'm';
|
||||
this->pos += ANSI_RESET_LEN;
|
||||
}
|
||||
}
|
||||
void strip_trailing_newlines_() {
|
||||
while (this->pos > 0 && this->data[this->pos - 1] == '\n')
|
||||
this->pos--;
|
||||
|
||||
@@ -233,7 +233,11 @@ class Logger final : public Component {
|
||||
void cdc_loop_();
|
||||
#endif
|
||||
void process_messages_();
|
||||
#if defined(USE_HOST) || defined(USE_ZEPHYR)
|
||||
void write_msg_(const char *msg, uint16_t len);
|
||||
#else
|
||||
inline void write_msg_(const char *msg, uint16_t len); // Defined in platform-specific logger_*.h
|
||||
#endif
|
||||
|
||||
// Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator
|
||||
// thread_name: name of the calling thread/task, or nullptr for main task (callers already know which task they're on)
|
||||
@@ -366,7 +370,7 @@ class Logger final : public Component {
|
||||
bool non_main_task_recursion_guard_{false}; // Shared guard for all non-main tasks on LibreTiny
|
||||
#endif
|
||||
#else
|
||||
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
||||
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
||||
#endif
|
||||
|
||||
// Large buffer placed last to keep frequently-accessed member offsets small
|
||||
@@ -498,3 +502,15 @@ class LoggerMessageTrigger final : public Trigger<uint8_t, const char *, const c
|
||||
};
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
||||
// Platform-specific inline implementations of write_msg_()
|
||||
// Must be included after the Logger class definition is complete
|
||||
#if defined(USE_ESP32)
|
||||
#include "logger_esp32.h"
|
||||
#elif defined(USE_ESP8266)
|
||||
#include "logger_esp8266.h"
|
||||
#elif defined(USE_RP2040)
|
||||
#include "logger_rp2040.h"
|
||||
#elif defined(USE_LIBRETINY)
|
||||
#include "logger_libretiny.h"
|
||||
#endif
|
||||
|
||||
@@ -123,23 +123,6 @@ void Logger::pre_setup() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
#if defined(USE_LOGGER_UART_SELECTION_USB_CDC) || defined(USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG)
|
||||
// USB CDC/JTAG - single write including newline (already in buffer)
|
||||
// Use fwrite to stdout which goes through VFS to USB console
|
||||
//
|
||||
// Note: These defines indicate the user's YAML configuration choice (hardware_uart: USB_CDC/USB_SERIAL_JTAG).
|
||||
// They are ONLY defined when the user explicitly selects USB as the logger output in their config.
|
||||
// This is compile-time selection, not runtime detection - if USB is configured, it's always used.
|
||||
// There is no fallback to regular UART if "USB isn't connected" - that's the user's responsibility
|
||||
// to configure correctly for their hardware. This approach eliminates runtime overhead.
|
||||
fwrite(msg, 1, len, stdout);
|
||||
#else
|
||||
// Regular UART - single write including newline (already in buffer)
|
||||
uart_write_bytes(this->uart_num_, msg, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
const LogString *Logger::get_uart_selection_() {
|
||||
switch (this->uart_) {
|
||||
case UART_SELECTION_UART0:
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include "esphome/core/helpers.h"
|
||||
#include <driver/uart.h>
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
inline void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
#if defined(USE_LOGGER_UART_SELECTION_USB_CDC) || defined(USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG)
|
||||
// USB CDC/JTAG - single write including newline (already in buffer)
|
||||
// Use fwrite to stdout which goes through VFS to USB console
|
||||
//
|
||||
// Note: These defines indicate the user's YAML configuration choice (hardware_uart: USB_CDC/USB_SERIAL_JTAG).
|
||||
// They are ONLY defined when the user explicitly selects USB as the logger output in their config.
|
||||
// This is compile-time selection, not runtime detection - if USB is configured, it's always used.
|
||||
// There is no fallback to regular UART if "USB isn't connected" - that's the user's responsibility
|
||||
// to configure correctly for their hardware. This approach eliminates runtime overhead.
|
||||
fwrite(msg, 1, len, stdout);
|
||||
#else
|
||||
// Regular UART - single write including newline (already in buffer)
|
||||
uart_write_bytes(this->uart_num_, msg, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
||||
#endif
|
||||
@@ -28,11 +28,6 @@ void Logger::pre_setup() {
|
||||
ESP_LOGI(TAG, "Log initialized");
|
||||
}
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
// Single write with newline already in buffer (added by caller)
|
||||
this->hw_serial_->write(msg, len);
|
||||
}
|
||||
|
||||
const LogString *Logger::get_uart_selection_() {
|
||||
#if defined(USE_ESP8266_LOGGER_SERIAL)
|
||||
if (this->uart_ == UART_SELECTION_UART0_SWAP) {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
// Single write with newline already in buffer (added by caller)
|
||||
inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); }
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
||||
#endif
|
||||
@@ -49,8 +49,6 @@ void Logger::pre_setup() {
|
||||
ESP_LOGI(TAG, "Log initialized");
|
||||
}
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); }
|
||||
|
||||
const LogString *Logger::get_uart_selection_() {
|
||||
switch (this->uart_) {
|
||||
case UART_SELECTION_DEFAULT:
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_LIBRETINY
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
// Single write with newline already in buffer (added by caller)
|
||||
inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); }
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
||||
#endif
|
||||
@@ -34,11 +34,6 @@ void Logger::pre_setup() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
// Single write with newline already in buffer (added by caller)
|
||||
this->hw_serial_->write(msg, len);
|
||||
}
|
||||
|
||||
const LogString *Logger::get_uart_selection_() {
|
||||
switch (this->uart_) {
|
||||
case UART_SELECTION_UART0:
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_RP2040
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
// Single write with newline already in buffer (added by caller)
|
||||
inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); }
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user