nghttpd does not support larger frames requested by a client
With http2, the client can request larger frame sizes in order to improve efficiency.
After requesting the larger size, the frames returned by nghttpd are still the default 16k.
The offending code is in nghttp2_session.c:1814
window_size = nghttp2_session_enforce_flow_control_limits(
session, stream, NGHTTP2_DATA_PAYLOADLEN);
NGHTTP2_DATA_PAYLOADLEN is a constant of 16k - the framesize minimum.
I am not sure the PR is the best solution. There is a dependency on the write buffer size. If this is too small, the call fails with NGHTTP2_ERR_WOULDBLOCK and the transfer stops. I don't think this behavior is correct.
With the changes:
using a Go client: 16k frames = 1.9 GB/s 256k frames = 2.9 GB/s
using h2load: 16k frames = 3.0 GB/s 256k frames = 3.7 GB/s
So even using h2load it 20% faster with the larger frames.
In my testing, it is not the size of frame but the size of buffer that increases the number. I think the framing overhead is negligible if it is implemented properly. The large frame size causes number of issues, including slow (or too late) prioritization propagation, increased memory usage by large buffers.
I don't disagree in the case of nghttp - but it's interface is not exactly "standard".
And a few counter points:
- Both Java and Go clients benefit tremendously from the changes.
- Profiling of both clients and servers show contention/overhead in the frame processing. This makes sense since a single stream has multiple servers and clients multiplexed onto it - so there must be concurrency issues to make this happen and it happens in user-space.
- The spec specifically calls for this capability. You can ask why? It came from SPDY - it was obvious that high throughput connections benefit from larger frames based on typical implementations.
- A system doing complex communications would most like use a large and small framed connection - to avoid the slow propagation issues.
- The tests I wrote use locally generated in-memory data streams - no disk IO - so the frame overhead processing is more apparent. I would need to write a custom nghttpd server to implement this.
At the end of the day, the spec calls for this so I think the reference implementation should properly support it.
https://nghttp2.org/documentation/types.html#c.nghttp2_data_source_read_length_callback should be used to select the frame size.
So far, only go and java implementations suffer from the frame size. It means they might choose the wrong architecture. If so, it would be better to let them reconsider the design rather than asking the other server or client vendors to accept and use larger frames.
If I remembered it correctly, the frame size extension was introduced in the last minute change. There were lots of discussions about it, and in order to just get consensus, the frame size field was extended to 3 bytes, without the proof of any real numbers, and only with the speculation that the future network might need this.
That said, libnghttp2 has an interface to enlarge frame size (I had no plan to add it, but someone submitted PR). I do not feel the need to add the capability to extend frame size for nghttpd because the difference is negligible or not noticeable.
As I pointed out, the current frame size handling in nghttpd is broken. I created a PR #1650 to demonstrate. You can run this in conjunction with the -f option of h2load and using any frame size greater than the write buffer (64k) will cause the transfer to hang indefinitely.
Yes, it needs larger buffers for larger frames. I just have no plan to add that capability to nghttpd.
You don't need to have a larger write buffer everywhere. Why not recreate the write buffer for the connection when the server receives a max_frame_size setting update?
In any case, I don't think hanging the transfer is correct. If anything, the server should cap the requested size from the callback to the write buffer size - essentially ignoring the request to change the max size.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.