]> git.kaiwu.me - nginx.git/commitdiff
HTTP/3: delayed Insert Count Increment instruction.
authorRoman Arutyunyan <arut@nginx.com>
Thu, 27 Jan 2022 09:20:47 +0000 (12:20 +0300)
committerRoman Arutyunyan <arut@nginx.com>
Thu, 27 Jan 2022 09:20:47 +0000 (12:20 +0300)
Sending the instruction is delayed until the end of the current event cycle.
Delaying the instruction is allowed by quic-qpack-21, section 2.2.2.3.
The goal is to reduce the amount of data sent back to client by accumulating
several inserts in one instruction and sometimes not sending the instruction at
all, if Section Acknowledgement was sent just before it.

src/http/v3/ngx_http_v3.c
src/http/v3/ngx_http_v3_parse.c
src/http/v3/ngx_http_v3_table.c
src/http/v3/ngx_http_v3_table.h

index 29b07e025050e74e849b0baf197c4bca667e0b1b..84bb8f60146118515900fa21949ac98c882690dd 100644 (file)
@@ -47,6 +47,10 @@ ngx_http_v3_init_session(ngx_connection_t *c)
     h3c->keepalive.handler = ngx_http_v3_keepalive_handler;
     h3c->keepalive.cancelable = 1;
 
+    h3c->table.send_insert_count.log = pc->log;
+    h3c->table.send_insert_count.data = pc;
+    h3c->table.send_insert_count.handler = ngx_http_v3_inc_insert_count_handler;
+
     cln = ngx_pool_cleanup_add(pc->pool, 0);
     if (cln == NULL) {
         goto failed;
@@ -93,6 +97,10 @@ ngx_http_v3_cleanup_session(void *data)
     if (h3c->keepalive.timer_set) {
         ngx_del_timer(&h3c->keepalive);
     }
+
+    if (h3c->table.send_insert_count.posted) {
+        ngx_delete_posted_event(&h3c->table.send_insert_count);
+    }
 }
 
 
index 25c1edf6d5ae1dc69968b0fb1be391b60f90b549..cd70bd3bf604640f2694a5cdee00ff091933f1bb 100644 (file)
@@ -395,6 +395,8 @@ done:
         if (ngx_http_v3_send_ack_section(c, c->quic->id) != NGX_OK) {
             return NGX_ERROR;
         }
+
+        ngx_http_v3_ack_insert_count(c, st->prefix.insert_count);
     }
 
     st->state = sw_start;
index c6d543ac440f43c32358164b522a840b9e968e7f..22dc3790189d14d435a905523a81b37d35a9aae9 100644 (file)
@@ -232,11 +232,9 @@ ngx_http_v3_insert(ngx_connection_t *c, ngx_str_t *name, ngx_str_t *value)
     dt->elts[dt->nelts++] = field;
     dt->size += size;
 
-    /* TODO increment can be sent less often */
+    dt->insert_count++;
 
-    if (ngx_http_v3_send_inc_insert_count(c, 1) != NGX_OK) {
-        return NGX_ERROR;
-    }
+    ngx_post_event(&dt->send_insert_count, &ngx_posted_events);
 
     if (ngx_http_v3_new_entry(c) != NGX_OK) {
         return NGX_ERROR;
@@ -246,6 +244,34 @@ ngx_http_v3_insert(ngx_connection_t *c, ngx_str_t *name, ngx_str_t *value)
 }
 
 
+void
+ngx_http_v3_inc_insert_count_handler(ngx_event_t *ev)
+{
+    ngx_connection_t             *c;
+    ngx_http_v3_session_t        *h3c;
+    ngx_http_v3_dynamic_table_t  *dt;
+
+    c = ev->data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http3 inc insert count handler");
+
+    h3c = ngx_http_v3_get_session(c);
+    dt = &h3c->table;
+
+    if (dt->insert_count > dt->ack_insert_count) {
+        if (ngx_http_v3_send_inc_insert_count(c,
+                                       dt->insert_count - dt->ack_insert_count)
+            != NGX_OK)
+        {
+            return;
+        }
+
+        dt->ack_insert_count = dt->insert_count;
+    }
+}
+
+
 ngx_int_t
 ngx_http_v3_set_capacity(ngx_connection_t *c, ngx_uint_t capacity)
 {
@@ -607,6 +633,21 @@ ngx_http_v3_check_insert_count(ngx_connection_t *c, ngx_uint_t insert_count)
 }
 
 
+void
+ngx_http_v3_ack_insert_count(ngx_connection_t *c, uint64_t insert_count)
+{
+    ngx_http_v3_session_t        *h3c;
+    ngx_http_v3_dynamic_table_t  *dt;
+
+    h3c = ngx_http_v3_get_session(c);
+    dt = &h3c->table;
+
+    if (dt->ack_insert_count < insert_count) {
+        dt->ack_insert_count = insert_count;
+    }
+}
+
+
 static void
 ngx_http_v3_unblock(void *data)
 {
index 6f88b35b91992273b1f586fbd96e089ab47adbad..1c2fb17b9c4f5c413822be1b35aee604ed9d476a 100644 (file)
@@ -26,9 +26,13 @@ typedef struct {
     ngx_uint_t                    base;
     size_t                        size;
     size_t                        capacity;
+    uint64_t                      insert_count;
+    uint64_t                      ack_insert_count;
+    ngx_event_t                   send_insert_count;
 } ngx_http_v3_dynamic_table_t;
 
 
+void ngx_http_v3_inc_insert_count_handler(ngx_event_t *ev);
 void ngx_http_v3_cleanup_table(ngx_http_v3_session_t *h3c);
 ngx_int_t ngx_http_v3_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic,
     ngx_uint_t index, ngx_str_t *value);
@@ -46,6 +50,7 @@ ngx_int_t ngx_http_v3_decode_insert_count(ngx_connection_t *c,
     ngx_uint_t *insert_count);
 ngx_int_t ngx_http_v3_check_insert_count(ngx_connection_t *c,
     ngx_uint_t insert_count);
+void ngx_http_v3_ack_insert_count(ngx_connection_t *c, uint64_t insert_count);
 ngx_int_t ngx_http_v3_set_param(ngx_connection_t *c, uint64_t id,
     uint64_t value);