mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Reserve space in the frame helper when we know in advance how much we need (#8716)
This commit is contained in:
		| @@ -5,6 +5,7 @@ | |||||||
| #include "esphome/core/helpers.h" | #include "esphome/core/helpers.h" | ||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "proto.h" | #include "proto.h" | ||||||
|  | #include "api_pb2_size.h" | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| @@ -574,6 +575,8 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) { | |||||||
|  |  | ||||||
|   if (!tx_buf_.empty()) { |   if (!tx_buf_.empty()) { | ||||||
|     // tx buf not empty, can't write now because then stream would be inconsistent |     // tx buf not empty, can't write now because then stream would be inconsistent | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + total_write_len); | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), |       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), | ||||||
|                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); |                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); | ||||||
| @@ -584,6 +587,8 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) { | |||||||
|   ssize_t sent = socket_->writev(iov, iovcnt); |   ssize_t sent = socket_->writev(iov, iovcnt); | ||||||
|   if (is_would_block(sent)) { |   if (is_would_block(sent)) { | ||||||
|     // operation would block, add buffer to tx_buf |     // operation would block, add buffer to tx_buf | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + total_write_len); | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), |       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), | ||||||
|                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); |                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); | ||||||
| @@ -596,6 +601,10 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) { | |||||||
|     return APIError::SOCKET_WRITE_FAILED; |     return APIError::SOCKET_WRITE_FAILED; | ||||||
|   } else if ((size_t) sent != total_write_len) { |   } else if ((size_t) sent != total_write_len) { | ||||||
|     // partially sent, add end to tx_buf |     // partially sent, add end to tx_buf | ||||||
|  |     size_t remaining = total_write_len - sent; | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + remaining); | ||||||
|  |  | ||||||
|     size_t to_consume = sent; |     size_t to_consume = sent; | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       if (to_consume >= iov[i].iov_len) { |       if (to_consume >= iov[i].iov_len) { | ||||||
| @@ -933,6 +942,8 @@ APIError APIPlaintextFrameHelper::write_packet(uint16_t type, const uint8_t *pay | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   std::vector<uint8_t> header; |   std::vector<uint8_t> header; | ||||||
|  |   header.reserve(1 + api::ProtoSize::varint(static_cast<uint32_t>(payload_len)) + | ||||||
|  |                  api::ProtoSize::varint(static_cast<uint32_t>(type))); | ||||||
|   header.push_back(0x00); |   header.push_back(0x00); | ||||||
|   ProtoVarInt(payload_len).encode(header); |   ProtoVarInt(payload_len).encode(header); | ||||||
|   ProtoVarInt(type).encode(header); |   ProtoVarInt(type).encode(header); | ||||||
| @@ -994,6 +1005,8 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt | |||||||
|  |  | ||||||
|   if (!tx_buf_.empty()) { |   if (!tx_buf_.empty()) { | ||||||
|     // tx buf not empty, can't write now because then stream would be inconsistent |     // tx buf not empty, can't write now because then stream would be inconsistent | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + total_write_len); | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), |       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), | ||||||
|                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); |                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); | ||||||
| @@ -1004,6 +1017,8 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt | |||||||
|   ssize_t sent = socket_->writev(iov, iovcnt); |   ssize_t sent = socket_->writev(iov, iovcnt); | ||||||
|   if (is_would_block(sent)) { |   if (is_would_block(sent)) { | ||||||
|     // operation would block, add buffer to tx_buf |     // operation would block, add buffer to tx_buf | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + total_write_len); | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), |       tx_buf_.insert(tx_buf_.end(), reinterpret_cast<uint8_t *>(iov[i].iov_base), | ||||||
|                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); |                      reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].iov_len); | ||||||
| @@ -1016,6 +1031,10 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt | |||||||
|     return APIError::SOCKET_WRITE_FAILED; |     return APIError::SOCKET_WRITE_FAILED; | ||||||
|   } else if ((size_t) sent != total_write_len) { |   } else if ((size_t) sent != total_write_len) { | ||||||
|     // partially sent, add end to tx_buf |     // partially sent, add end to tx_buf | ||||||
|  |     size_t remaining = total_write_len - sent; | ||||||
|  |     // Reserve space upfront to avoid multiple reallocations | ||||||
|  |     tx_buf_.reserve(tx_buf_.size() + remaining); | ||||||
|  |  | ||||||
|     size_t to_consume = sent; |     size_t to_consume = sent; | ||||||
|     for (int i = 0; i < iovcnt; i++) { |     for (int i = 0; i < iovcnt; i++) { | ||||||
|       if (to_consume >= iov[i].iov_len) { |       if (to_consume >= iov[i].iov_len) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user