]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: use sched call time for pacing
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 21 Nov 2024 15:20:15 +0000 (16:20 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 25 Nov 2024 10:21:45 +0000 (11:21 +0100)
QUIC pacing was recently implemented to limit burst and improve overall
bandwidth. This is used only for MUX STREAM emission. Pacing requires
nanosecond resolution. As such, it used now_cpu_time() which relies on
clock_gettime() syscall.

The usage of clock_gettime() has several drawbacks :
* it is a syscall and thus requires a context-switch which may hurt
  performance
* it is not be available on all systems
* timestamp is retrieved multiple times during a single task execution,
  thus yielding different values which may tamper pacing calculation

Improve this by using task_mono_time() instead. This returns task call
time from the scheduler thread context. It requires the flag
TASK_F_WANTS_TIME on QUIC MUX tasklet to force the scheduler to update
call time with now_mono_time(). This solves every limitations listed
above :
* syscall invokation is only performed once before tasklet execution,
  thus reducing context-switch impact
* on non compatible system, a millisecond timer is used as a fallback
  which should ensure that pacing works decently for them
* timer value is now guaranteed to be fixed duing task execution

include/haproxy/mux_quic-t.h
src/mux_quic.c
src/quic_pacing.c

index a0f8e0dbdf5503e0b83cb9347cb049658e90dc30..2fd3edab86fef166427d8adc3ceb18c2309cbfb2 100644 (file)
@@ -18,6 +18,7 @@
 #include <haproxy/quic_pacing-t.h>
 #include <haproxy/quic_stream-t.h>
 #include <haproxy/stconn-t.h>
+#include <haproxy/task-t.h>
 #include <haproxy/time-t.h>
 
 /* Stream types */
index 03a7b293820ec0739f07849e38ba09d91a8122f9..64e6df2113121f7c4e4ca491f2c0f340fa41e41f 100644 (file)
@@ -2996,6 +2996,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
 
        qcc->wait_event.tasklet->process = qcc_io_cb;
        qcc->wait_event.tasklet->context = qcc;
+       qcc->wait_event.tasklet->state  |= TASK_F_WANTS_TIME;
        qcc->wait_event.events = 0;
 
        qcc->proxy = prx;
index 7b1e5b9dc195eadb2e3bd2ebbe009eb362960dea..9dfa35206227ffceaeda230096db57db4f67748c 100644 (file)
@@ -1,16 +1,17 @@
 #include <haproxy/quic_pacing.h>
 
 #include <haproxy/quic_tx.h>
+#include <haproxy/task.h>
 
 /* Returns true if <pacer> timer is expired and emission can be retried. */
 int quic_pacing_expired(const struct quic_pacer *pacer)
 {
-       return !pacer->next || pacer->next <= now_mono_time();
+       return !pacer->next || pacer->next <= task_mono_time();
 }
 
 /* Notify <pacer> about an emission of <sent> count of datagrams. */
 void quic_pacing_sent_done(struct quic_pacer *pacer, int sent)
 {
-       pacer->next = now_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc) * sent;
+       pacer->next = task_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc) * sent;
        pacer->last_sent = sent;
 }