Send small static files with the headers and large bodies without a copy - #2589
Merged
Merged
Conversation
A file served from a mount point or through set_file_content() left in two writes, one for the status line and headers and one for the body, because the body came from a content provider. A small file is now read into the header buffer so the whole response leaves in a single write. Only file-backed providers are coalesced this way: a user-supplied provider may produce its data over time, and holding the headers back until it finishes would stall the client. A large set_content() body was copied into the header buffer before being sent. A body of CPPHTTPLIB_SEND_BUFSIZ or more is now written directly after the headers, which saves the copy at the cost of one extra write.
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 takes the two gains measured on #2541 with a change confined to
Server::write_response_core(), without adding public API or platform-specific send code.set_file_content()(underCPPHTTPLIB_SEND_BUFSIZ) is read into the header buffer, so the status line, the headers and the body leave in a single write. Before, the body came from a content provider and always went out in a second write.set_content()body (CPPHTTPLIB_SEND_BUFSIZor more) is written directly after the headers instead of being copied into the header buffer first.Only file-backed providers are coalesced. A user-supplied provider may produce its data over time, and holding the headers back until it finishes would stall the client (
ErrorHandlingTest.StreamReadTimeoutcovers this). A privateResponse::is_file_content_provider_flag marks the file case; every provider setter resets it.benchmark/ab.sh, 7 alternating rounds, ratio of medians against master:/static/small.js/large(1 MiB)/static/large.bin(1 MiB)/Against #2541 itself the only separated differences were
/static/large.binplain (0.954x), where #2541 sends the headers and a large file in onesendmsg(), and/static/small.jsTLS (0.983x).Thanks to @gsmecher for the idea and the analysis in #2541.