aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2025-04-04 17:39:05 +0400
committerRoman Arutyunyan <arutyunyan.roman@gmail.com>2025-04-15 19:01:36 +0400
commit2fb32ff24d431211b673ff9c854352ca0c74e27c (patch)
tree37571cb83b0abd44f5c08cf59ad22b47bda0a894
parentf9a7e7cc11e71b2c62d4c5b9ac4feb7e92913c64 (diff)
downloadnginx-2fb32ff24d431211b673ff9c854352ca0c74e27c.tar.gz
nginx-2fb32ff24d431211b673ff9c854352ca0c74e27c.zip
QUIC: optimized connection frame threshold.
Previosly the threshold was hardcoded at 10000. This value is too low for high BDP networks. For example, if all frames are STREAM frames, and MTU is 1500, the upper limit for congestion window would be roughly 15M (10000 * 1500). With 100ms RTT it's just a 1.2Gbps network (15M * 10 * 8). In reality, the limit is even lower because of other frame types. Also, the number of frames that could be used simultaneously depends on the total amount of data buffered in all server streams, and client flow control. The change sets frame threshold based on max concurrent streams and stream buffer size, the product of which is the maximum number of in-flight stream data in all server streams at any moment. The value is divided by 2000 to account for a typical MTU 1500 and the fact that not all frames are STREAM frames.
-rw-r--r--src/event/quic/ngx_event_quic.c4
-rw-r--r--src/event/quic/ngx_event_quic_connection.h1
-rw-r--r--src/event/quic/ngx_event_quic_frames.c2
3 files changed, 6 insertions, 1 deletions
diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
index 49d30e82a..4682ecad9 100644
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -315,6 +315,10 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE;
qc->congestion.recovery_start = ngx_current_msec - 1;
+ qc->max_frames = (conf->max_concurrent_streams_uni
+ + conf->max_concurrent_streams_bidi)
+ * conf->stream_buffer_size / 2000;
+
if (pkt->validated && pkt->retried) {
qc->tp.retry_scid.len = pkt->dcid.len;
qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid);
diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h
index 716d62308..04cda859e 100644
--- a/src/event/quic/ngx_event_quic_connection.h
+++ b/src/event/quic/ngx_event_quic_connection.h
@@ -261,6 +261,7 @@ struct ngx_quic_connection_s {
ngx_buf_t *free_shadow_bufs;
ngx_uint_t nframes;
+ ngx_uint_t max_frames;
#ifdef NGX_QUIC_DEBUG_ALLOC
ngx_uint_t nbufs;
ngx_uint_t nshadowbufs;
diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c
index 6ea908cc1..888e8bda2 100644
--- a/src/event/quic/ngx_event_quic_frames.c
+++ b/src/event/quic/ngx_event_quic_frames.c
@@ -214,7 +214,7 @@ ngx_quic_alloc_frame(ngx_connection_t *c)
"quic reuse frame n:%ui", qc->nframes);
#endif
- } else if (qc->nframes < 10000) {
+ } else if (qc->nframes < qc->max_frames) {
frame = ngx_palloc(c->pool, sizeof(ngx_quic_frame_t));
if (frame == NULL) {
return NULL;