From 61031503dc8087c2c17cd2142c9b4b19062f90c4 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 25 Sep 2026 14:16:36 +0000 Subject: [PATCH] HTTP/2: optimized queuing of DATA frames With priorities from RFC 9218, streams of the same urgency are ordered by their identifiers, so queuing a frame of an older stream traverses the frames of all newer ones. Frames queued in ngx_http_v2_send_chain() belong to a single stream, and hence to a single position in the output queue, which does not change while they are queued. Now the position is searched once per call. --- src/http/v2/ngx_http_v2.h | 18 ++++++++++++++---- src/http/v2/ngx_http_v2_filter_module.c | 8 +++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 797e3e8b1..eb3cd008e 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -261,9 +261,11 @@ ngx_http_v2_stream_precedes(ngx_http_v2_stream_t *s, } -static ngx_inline void -ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c, - ngx_http_v2_out_frame_t *frame) +/* all frames of a stream are queued at the same position */ + +static ngx_inline ngx_http_v2_out_frame_t ** +ngx_http_v2_queue_position(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream) { ngx_http_v2_out_frame_t **out; @@ -273,11 +275,19 @@ ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c, break; } - if (ngx_http_v2_stream_precedes((*out)->stream, frame->stream)) { + if (ngx_http_v2_stream_precedes((*out)->stream, stream)) { break; } } + return out; +} + + +static ngx_inline void +ngx_http_v2_queue_frame(ngx_http_v2_out_frame_t **out, + ngx_http_v2_out_frame_t *frame) +{ frame->next = *out; *out = frame; } diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 4165c1c06..c82cbbddf 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -1068,7 +1068,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) ngx_http_request_t *r; ngx_http_v2_stream_t *stream; ngx_http_v2_loc_conf_t *h2lcf; - ngx_http_v2_out_frame_t *frame, *trailers; + ngx_http_v2_out_frame_t *frame, *trailers, **fn; ngx_http_v2_connection_t *h2c; r = fc->data; @@ -1156,6 +1156,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) trailers = NGX_HTTP_V2_NO_TRAILERS; + fn = ngx_http_v2_queue_position(h2c, stream); + #if (NGX_SUPPRESS_WARN) cl = NULL; #endif @@ -1236,7 +1238,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) return NGX_CHAIN_ERROR; } - ngx_http_v2_queue_frame(h2c, frame); + ngx_http_v2_queue_frame(fn, frame); h2c->send_window -= frame_size; @@ -1247,7 +1249,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) if (in == NULL) { if (trailers != NGX_HTTP_V2_NO_TRAILERS) { - ngx_http_v2_queue_frame(h2c, trailers); + ngx_http_v2_queue_frame(fn, trailers); stream->queued++; } -- 2.47.3