-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Refactor API frame helpers to enable buffer reuse #8825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hey there @OttoWinter, mind taking a look at this pull request as it has been labeled with an integration ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the ESPHome API frame helpers to enable efficient buffer reuse by switching from raw data pointers to using ProtoWriteBuffer objects and updating header/footer management accordingly.
- Refactored write methods to use ProtoWriteBuffer instead of raw pointers.
- Added methods to provide protocol-specific header padding and footer sizes.
- Updated documentation and connection buffer management to accommodate the new buffer reuse strategy.
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
esphome/components/api/protocol_details.md | Added detailed documentation for both Noise and Plaintext protocol frames. |
esphome/components/api/proto.h | Introduced a new encode_to_buffer method in ProtoVarInt. |
esphome/components/api/api_frame_helper.h | Updated APIFrameHelper interface and constructors in derived classes. |
esphome/components/api/api_frame_helper.cpp | Refactored write methods for Noise and Plaintext to support ProtoWriteBuffer. |
esphome/components/api/api_connection.h/cpp | Adjusted buffer pre-allocation/insertion and write method calls. |
Comments suppressed due to low confidence (1)
esphome/components/api/api_frame_helper.h:96
- Avoid performing a double move on 'ctx'. Use a single std::move(ctx) to improve code clarity and avoid any unintended side effects.
APINoiseFrameHelper(std::unique_ptr<socket::Socket> socket, std::shared_ptr<APINoiseContext> ctx) : socket_(std::move(socket)), ctx_(std::move(std::move(ctx))) {
Thanks. I'll fix the conflicts on #8805 after the PyCon dinner |
#8805 will heavily conflict. This one has more value so it should merge first.
What does this implement/fix?
This PR refactors the ESPHome API component's frame helper system to enable efficient buffer reuse by passing
ProtoWriteBuffer
objects instead of raw data pointers. This optimization significantly reduces memory allocations and improves performance for high-frequency message exchanges.API Frame Helper Interface Updates
Added frame padding and footer size methods:
frame_header_padding()
: Returns bytes reserved for protocol headers (7 for Noise, 6 for Plaintext)frame_footer_size()
: Returns footer size (16 bytes for Noise MAC, 0 for Plaintext)Renamed and updated write method:
write_packet()
→write_protobuf_packet()
ProtoWriteBuffer*
instead of raw data pointersBuffer Management Strategy
The new implementation uses a single reusable buffer with pre-allocated padding:
Noise performance changes
Before: ~66% performance penalty for encrypted connections --- it was all suffering from memory copy
After: ~7% performance penalty for encrypted connections
base branch
add_api_stats
testing branch
reuse_buffer_api_stats
Read is also somehow faster without the other upcoming optmizations but its likely because its not churning memory anymore -- avg read_packet: 0.19ms → 0.07ms (63% faster in new version)
Single Loop Period Stats (Last 60s)
Loop Total Stats (Since Boot)
Plaintext performance changes
As expected its not much difference: write_packet operations (6% faster). The overall loop time decreased by ~3.6%
Seems to help a little bit with free memory as well

Types of changes
Related issue or feature (if applicable):
Pull request in esphome-docs with documentation (if applicable):
Testing
Test Environment
Example entry for
config.yaml
:# Example config.yaml
Checklist:
tests/
folder).If user exposed functionality or configuration variables are added/changed: