mirror of
https://github.com/esphome/esphome.git
synced 2025-09-02 19:32:19 +01:00
[api] Optimize message buffer allocation and eliminate redundant methods (#10231)
This commit is contained in:
@@ -289,16 +289,26 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
|
|||||||
return 0; // Doesn't fit
|
return 0; // Doesn't fit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate buffer space - pass payload size, allocation functions add header/footer space
|
|
||||||
ProtoWriteBuffer buffer = is_single ? conn->allocate_single_message_buffer(calculated_size)
|
|
||||||
: conn->allocate_batch_message_buffer(calculated_size);
|
|
||||||
|
|
||||||
// Get buffer size after allocation (which includes header padding)
|
// Get buffer size after allocation (which includes header padding)
|
||||||
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
|
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
|
||||||
size_t size_before_encode = shared_buf.size();
|
|
||||||
|
if (is_single || conn->flags_.batch_first_message) {
|
||||||
|
// Single message or first batch message
|
||||||
|
conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size);
|
||||||
|
if (conn->flags_.batch_first_message) {
|
||||||
|
conn->flags_.batch_first_message = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Batch message second or later
|
||||||
|
// Add padding for previous message footer + this message header
|
||||||
|
size_t current_size = shared_buf.size();
|
||||||
|
shared_buf.reserve(current_size + total_calculated_size);
|
||||||
|
shared_buf.resize(current_size + footer_size + header_padding);
|
||||||
|
}
|
||||||
|
|
||||||
// Encode directly into buffer
|
// Encode directly into buffer
|
||||||
msg.encode(buffer);
|
size_t size_before_encode = shared_buf.size();
|
||||||
|
msg.encode({&shared_buf});
|
||||||
|
|
||||||
// Calculate actual encoded size (not including header that was already added)
|
// Calculate actual encoded size (not including header that was already added)
|
||||||
size_t actual_payload_size = shared_buf.size() - size_before_encode;
|
size_t actual_payload_size = shared_buf.size() - size_before_encode;
|
||||||
@@ -1620,14 +1630,6 @@ bool APIConnection::schedule_batch_() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
|
|
||||||
|
|
||||||
ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
|
|
||||||
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->flags_.batch_first_message);
|
|
||||||
this->flags_.batch_first_message = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APIConnection::process_batch_() {
|
void APIConnection::process_batch_() {
|
||||||
// Ensure PacketInfo remains trivially destructible for our placement new approach
|
// Ensure PacketInfo remains trivially destructible for our placement new approach
|
||||||
static_assert(std::is_trivially_destructible<PacketInfo>::value,
|
static_assert(std::is_trivially_destructible<PacketInfo>::value,
|
||||||
@@ -1735,7 +1737,7 @@ void APIConnection::process_batch_() {
|
|||||||
}
|
}
|
||||||
remaining_size -= payload_size;
|
remaining_size -= payload_size;
|
||||||
// Calculate where the next message's header padding will start
|
// Calculate where the next message's header padding will start
|
||||||
// Current buffer size + footer space (that prepare_message_buffer will add for this message)
|
// Current buffer size + footer space for this message
|
||||||
current_offset = shared_buf.size() + footer_size;
|
current_offset = shared_buf.size() + footer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -252,44 +252,21 @@ class APIConnection : public APIServerConnection {
|
|||||||
|
|
||||||
// Get header padding size - used for both reserve and insert
|
// Get header padding size - used for both reserve and insert
|
||||||
uint8_t header_padding = this->helper_->frame_header_padding();
|
uint8_t header_padding = this->helper_->frame_header_padding();
|
||||||
|
|
||||||
// Get shared buffer from parent server
|
// Get shared buffer from parent server
|
||||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
||||||
|
this->prepare_first_message_buffer(shared_buf, header_padding,
|
||||||
|
reserve_size + header_padding + this->helper_->frame_footer_size());
|
||||||
|
return {&shared_buf};
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
|
||||||
shared_buf.clear();
|
shared_buf.clear();
|
||||||
// Reserve space for header padding + message + footer
|
// Reserve space for header padding + message + footer
|
||||||
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
|
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
|
||||||
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
|
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
|
||||||
shared_buf.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
|
shared_buf.reserve(total_size);
|
||||||
// Resize to add header padding so message encoding starts at the correct position
|
// Resize to add header padding so message encoding starts at the correct position
|
||||||
shared_buf.resize(header_padding);
|
shared_buf.resize(header_padding);
|
||||||
return {&shared_buf};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare buffer for next message in batch
|
|
||||||
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
|
|
||||||
// Get reference to shared buffer (it maintains state between batch messages)
|
|
||||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
|
||||||
|
|
||||||
if (is_first_message) {
|
|
||||||
shared_buf.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t current_size = shared_buf.size();
|
|
||||||
|
|
||||||
// Calculate padding to add:
|
|
||||||
// - First message: just header padding
|
|
||||||
// - Subsequent messages: footer for previous message + header padding for this message
|
|
||||||
size_t padding_to_add = is_first_message
|
|
||||||
? this->helper_->frame_header_padding()
|
|
||||||
: this->helper_->frame_header_padding() + this->helper_->frame_footer_size();
|
|
||||||
|
|
||||||
// Reserve space for padding + message
|
|
||||||
shared_buf.reserve(current_size + padding_to_add + message_size);
|
|
||||||
|
|
||||||
// Resize to add the padding bytes
|
|
||||||
shared_buf.resize(current_size + padding_to_add);
|
|
||||||
|
|
||||||
return {&shared_buf};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_to_clear_buffer(bool log_out_of_space);
|
bool try_to_clear_buffer(bool log_out_of_space);
|
||||||
@@ -297,10 +274,6 @@ class APIConnection : public APIServerConnection {
|
|||||||
|
|
||||||
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
|
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
|
||||||
|
|
||||||
// Buffer allocator methods for batch processing
|
|
||||||
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
|
||||||
ProtoWriteBuffer allocate_batch_message_buffer(uint16_t size);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Helper function to handle authentication completion
|
// Helper function to handle authentication completion
|
||||||
void complete_authentication_();
|
void complete_authentication_();
|
||||||
|
Reference in New Issue
Block a user