std.http.Client.fetch sends headers unnecessarily before the remaining payload, causing performance issues in some peculiar environments #22259
Labels
bug
Observed behavior contradicts documented or intended behavior
Zig Version
0.14.0-dev.2487+af89bb05d
Steps to Reproduce and Observed Behavior
While debugging a performance problem in a peculiar environment, I noticed that fetch flushes the headers to the connection stream before sending the rest of the payload. Depending on the size of the http headers and payload relative to the size of data that will fit in the underlying TCP/IP packets, the request will be spread across more packets than is necessary.
The relevant part of the "fetch" code in std.http.Client.zig looks like this (~line 1758):
and send is like this:
The "flush" call would cause any buffered data to be sent out in an IP packet, which will be unnecessarily small.
I know this seems like a trivial thing, but some environments are apparently very sensitive to this.
(The "peculiar environment" I'm working with is AWS Lambda. You make HTTP requests to interact with the AWS Lambda runtime. When the headers are flushed when posting the first handler response, AWS takes about 50 ms extra to accept the response. It normally takes < 1 ms. Apparently it really doesn't like the request header split from the request body. Of course, that's an AWS problem not a zig problem, but it still makes sense for fetch() to be efficient with how it sends requests.)
Expected Behavior
fetch() doesn't unnecessarily flush headers before sending the payload.
Additionally, it may make sense for the lower-level API to support this case. E.g, "send()" might have an option to flush the connection, or maybe there could be a "send_noflush()" function to support that case. Not sure the best way to expose the option, but I think there should be an option somewhere.
(As it is now, I can't use the standard library's http module, which seems like a shame.)
The text was updated successfully, but these errors were encountered: