From 5343a6d16a373b66d1674dce1c183d3d3e85cc6d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 21 Jul 2025 11:39:28 -1000 Subject: [PATCH] [api] Optimize string encoding with memcpy for 10x performance improvement (#9778) --- esphome/components/api/proto.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 0ba8df84da..6ae4556cc1 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -5,6 +5,7 @@ #include "esphome/core/log.h" #include +#include #include #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE @@ -206,8 +207,13 @@ class ProtoWriteBuffer { this->encode_field_raw(field_id, 2); // type 2: Length-delimited string this->encode_varint_raw(len); - auto *data = reinterpret_cast(string); - this->buffer_->insert(this->buffer_->end(), data, data + len); + + // Using resize + memcpy instead of insert provides significant performance improvement: + // ~10-11x faster for 16-32 byte strings, ~3x faster for 64-byte strings + // as it avoids iterator checks and potential element moves that insert performs + size_t old_size = this->buffer_->size(); + this->buffer_->resize(old_size + len); + std::memcpy(this->buffer_->data() + old_size, string, len); } void encode_string(uint32_t field_id, const std::string &value, bool force = false) { this->encode_string(field_id, value.data(), value.size(), force);