mirror of
https://github.com/esphome/esphome.git
synced 2026-09-19 11:08:38 +00:00
[api] Restore single-buffer write_raw_ overload to keep inline failure path small
Moving iovec construction into write_raw_fast_ caused an 8% regression by enlarging the inlined failure path. The 33-byte out-of-line wrapper keeps the hot inline path minimal.
This commit is contained in:
@@ -112,8 +112,15 @@ APIError APIFrameHelper::drain_overflow_and_handle_errors_() {
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
// Slow path: handles partial writes, errors, and overflow buffering.
|
||||
// Called when the inline fast path in the header couldn't complete the write.
|
||||
// Single-buffer write path: wraps in iovec and delegates.
|
||||
APIError APIFrameHelper::write_raw_(const void *data, uint16_t len, ssize_t sent) {
|
||||
struct iovec iov = {const_cast<void *>(data), len};
|
||||
return this->write_raw_(&iov, 1, len, sent);
|
||||
}
|
||||
|
||||
// Handles partial writes, errors, and overflow buffering.
|
||||
// Called when the inline fast path in the header couldn't complete the write,
|
||||
// or directly from cold paths (handshake, error handling).
|
||||
// sent == -1 means either the fast path write returned -1, or there was overflow backlog.
|
||||
APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, ssize_t sent) {
|
||||
#ifdef HELPER_LOG_PACKETS
|
||||
|
||||
@@ -202,8 +202,7 @@ class APIFrameHelper {
|
||||
if (sent == static_cast<ssize_t>(len)) [[likely]]
|
||||
return APIError::OK;
|
||||
}
|
||||
struct iovec iov = {const_cast<void *>(data), len};
|
||||
return this->write_raw_(&iov, 1, len, sent);
|
||||
return this->write_raw_(data, len, sent);
|
||||
}
|
||||
inline APIError ESPHOME_ALWAYS_INLINE write_raw_fast_(const struct iovec *iov, int iovcnt, uint16_t total_write_len) {
|
||||
ssize_t sent = -1;
|
||||
@@ -215,7 +214,8 @@ class APIFrameHelper {
|
||||
return this->write_raw_(iov, iovcnt, total_write_len, sent);
|
||||
}
|
||||
|
||||
// Slow path (out-of-line): handle partial writes, errors, overflow buffering
|
||||
// Out-of-line write paths: handle partial writes, errors, overflow buffering
|
||||
APIError write_raw_(const void *data, uint16_t len, ssize_t sent = -1);
|
||||
APIError write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, ssize_t sent = -1);
|
||||
|
||||
// Socket ownership (4 bytes on 32-bit, 8 bytes on 64-bit)
|
||||
|
||||
@@ -537,8 +537,7 @@ APIError APINoiseFrameHelper::write_frame_(const uint8_t *data, uint16_t len) {
|
||||
header[2] = (uint8_t) len;
|
||||
|
||||
if (len == 0) {
|
||||
struct iovec iov = {header, 3};
|
||||
return this->write_raw_(&iov, 1, 3);
|
||||
return this->write_raw_(header, 3);
|
||||
}
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = header;
|
||||
|
||||
@@ -219,13 +219,11 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
"Bad indicator byte";
|
||||
char msg[INDICATOR_MSG_SIZE];
|
||||
memcpy_P(msg, MSG_PROGMEM, INDICATOR_MSG_SIZE);
|
||||
struct iovec iov = {msg, INDICATOR_MSG_SIZE};
|
||||
this->write_raw_(&iov, 1, INDICATOR_MSG_SIZE);
|
||||
this->write_raw_(msg, INDICATOR_MSG_SIZE);
|
||||
#else
|
||||
static const char MSG[] = "\x00"
|
||||
"Bad indicator byte";
|
||||
struct iovec iov = {const_cast<char *>(MSG), INDICATOR_MSG_SIZE};
|
||||
this->write_raw_(&iov, 1, INDICATOR_MSG_SIZE);
|
||||
this->write_raw_(MSG, INDICATOR_MSG_SIZE);
|
||||
#endif
|
||||
}
|
||||
return aerr;
|
||||
|
||||
Reference in New Issue
Block a user