mirror of
https://github.com/esphome/esphome.git
synced 2026-09-16 01:28:39 +00:00
[api] Merge varint length + memcpy into single pos scope in encode_string
Previously encode_string called encode_varint_raw(len) then encode_raw(data, len) as separate methods, each with their own __restrict__ pos scope. This caused a redundant store-load pair of pos_ between the two operations. Inline the length varint write and memcpy under a single local pos variable so the compiler can keep pos_ in a register across both operations. Eliminates one load-store pair per string encode.
This commit is contained in:
@@ -288,11 +288,17 @@ class ProtoWriteBuffer {
|
||||
return;
|
||||
|
||||
this->encode_field_raw(field_id, 2); // type 2: Length-delimited string
|
||||
this->encode_varint_raw(len);
|
||||
// Direct memcpy into pre-sized buffer — avoids push_back() per-byte capacity checks
|
||||
// and vector::insert() iterator overhead. ~10-11x faster for 16-32 byte strings.
|
||||
this->debug_check_bounds_(len);
|
||||
// Inline the length varint + memcpy under a single __restrict__ pos
|
||||
// to avoid a store-load pair between encode_varint_raw and encode_raw.
|
||||
this->debug_check_bounds_(1 + len);
|
||||
uint8_t *__restrict__ pos = this->pos_;
|
||||
if (len < 128) [[likely]] {
|
||||
*pos++ = static_cast<uint8_t>(len);
|
||||
} else {
|
||||
// Length >= 128: use slow path for the length varint, then re-hoist pos
|
||||
this->encode_varint_raw_slow_(len);
|
||||
pos = this->pos_;
|
||||
}
|
||||
std::memcpy(pos, string, len);
|
||||
this->pos_ = pos + len;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user