From 22bd92a87f835280200b42c6048d7e51bc99ea24 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 21 Nov 2024 16:20:15 +0100 Subject: [PATCH] MINOR: mux-quic: use sched call time for pacing 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 | 1 + src/mux_quic.c | 1 + src/quic_pacing.c | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index a0f8e0dbd..2fd3edab8 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -18,6 +18,7 @@ #include #include #include +#include #include /* Stream types */ diff --git a/src/mux_quic.c b/src/mux_quic.c index 03a7b2938..64e6df211 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -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; diff --git a/src/quic_pacing.c b/src/quic_pacing.c index 7b1e5b9dc..9dfa35206 100644 --- a/src/quic_pacing.c +++ b/src/quic_pacing.c @@ -1,16 +1,17 @@ #include #include +#include /* Returns true if 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 about an emission of 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; }