Stream iodata in bounded chunks#12
Draft
harmon25 wants to merge 2 commits into
Draft
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves TCP response sending in tcp_server by streaming nested iodata incrementally in bounded chunks (byte-size + entry-count limits), avoiding response-sized flattening and reducing peak memory usage/fragmentation on constrained targets (e.g., ESP32).
Changes:
- Replace full-response flattening with incremental iodata traversal (
next_chunk/2) and bounded chunk extraction insrc/tcp_server.erl. - Add ExUnit coverage for correctness of chunk boundaries, deep nesting, entry-count bounds, and invalid input handling.
- Update README and agent guidance to describe the new bounded chunking and partial-send retry behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/tcp_server.erl |
Implements bounded incremental iodata chunking and adjusts partial-send retry to only resend the unsent part of the current chunk. |
test/tcp_server_test.exs |
Adds tests validating chunking behavior, bounds, and error handling for invalid inputs. |
README.md |
Documents the incremental iodata chunking behavior and partial-send retry semantics. |
AGENTS.md |
Updates contributor guidance to reinforce “never flatten full responses” and describe bounded chunk traversal. |
Comment on lines
+416
to
+420
| case Rest of | ||
| [] -> ok; | ||
| _ -> receive after 0 -> ok end | ||
| end, | ||
| do_send_iodata(Socket, Rest, ChunkSize); |
There was a problem hiding this comment.
Fixed in the latest commit — the recursive do_send_iodata/3 call is now inside the _ -> branch so it's only reached when Rest is non-empty.
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.
This pull request significantly improves how large responses are sent over TCP by incrementally walking nested iodata structures instead of flattening them into large binaries. This change reduces memory usage and fragmentation, especially on memory-constrained devices like the ESP32, and introduces strict bounds on both chunk size and the number of iodata entries per chunk. The implementation is thoroughly tested to ensure correctness and robustness.
Incremental iodata chunking and bounded memory usage:
src/tcp_server.erl: Replaces the previous approach of flattening complete responses with incremental traversal of nested iodata, bounding both the byte size and entry count per chunk using the newnext_chunk/2function andMAX_CHUNK_ENTRIESconstant. This ensures that temporary allocations remain small regardless of total response size. Partial sends now retry only the unsent portion of the current chunk, never concatenating with the rest of the response. [1] [2]AGENTS.md,README.md: Updated documentation to explain the new chunking behavior, emphasizing that responses are never fully flattened and that partial sends are retried in a memory-efficient manner. [1] [2] [3]Testing and developer support:
src/tcp_server.erl: Exportsnext_chunk/2for testing when compiled withTESTdefined, facilitating direct verification of chunking logic.test/tcp_server_test.exs: Adds comprehensive tests for the new chunking logic, including preservation of nested iodata, enforcement of entry limits, and error handling for invalid input.Constants and configuration:
src/tcp_server.erl: Introduces and documents theMAX_CHUNK_ENTRIESconstant to prevent excessive cons cell allocations from highly fragmented iodata.