Repository navigation
WebSocket sends: no copy into a frame, encoded buffers taken rather than copied - #10
Merged
Merged
Conversation
A server's (unmasked) message is sent as the header then the data, rather than copied into a frame buffer first. What the connection can't send at once is queued in order as before, and if it can't be queued the send fails and the connection is closed, so a frame is never left part sent. A client's (masked) message is still built into a frame, as it has to be masked. Measured publishing camera frames from an ESP32-S3 with quad PSRAM: building the frame took up to 4-6 ms for a 29 KB frame and now takes nothing, and the longest publish went from 21-22 ms to 17-19 ms (13-16 ms to about 12 ms for 19 KB frames). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…her than copying it - A message whose buffer may be taken (RaftCore's CommsChannelMsg::isBufTakeable(), set on a RICREST message just encoded for sending) goes through a take path (WebServer SysMod, RaftWebServer, RaftWebConnManager, the responder, RaftWebSocketLink, RaftWebConnection): what the socket can't take at once (all but the first 5.7 KB of a camera frame) is kept by taking the buffer into the empty send queue, rather than copied into it. The buffer is only taken when one connection is on the channel; other messages and senders are unchanged. - The send queue keeps a read position: sending from it no longer erases what was sent from the front, which moved everything left each time (about 57 KB of copying in later loops for a 29 KB frame). Measured publishing camera frames from an ESP32-S3 with quad PSRAM: longest publish 13.4 ms for 28 KB frames (17-19 ms with the previous commit, 21-22 ms before), 10.7-11.2 ms for 18 KB frames, and more frames got through (1.8 a second at 2 Hz, was 1.4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Less main-loop time sending large WebSocket messages, such as published camera frames.
Changes
CommsChannelMsg::isBufTakeable(), set on a RICREST message just encoded for sending).RaftWebServer,RaftWebConnManager,RaftWebResponderWS,RaftWebSocketLink,RaftWebConnection.Measured
ESP32-S3 with quad PSRAM at 80 MHz, camera frames published over a WebSocket at 2 Hz, longest
Publishhold on the main loop:Every frame arrived as a valid JPEG, and more got through at SVGA: 1.8 a second, against 1.4.
Most of what's left is the HDLC encode (about 9-10 ms at SVGA). The rest is lwIP copying the first 5.7 KB.
A 32 KB TCP send buffer was also tried. It made the hold longer (20-21 ms at SVGA), because lwIP's copy costs more than the queue's.
Needs RaftCore with
CommsChannelMsg::isBufTakeable()(robdobsn/RaftCore#31, merged).The can-send check change (
lwip_select()) was pushed after this was merged, so it is in #11.🤖 Generated with Claude Code