]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: ratelimit timestamps
authorStefan Eissing <stefan@eissing.org>
Fri, 10 Jul 2026 09:47:48 +0000 (11:47 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 13 Jul 2026 09:53:00 +0000 (11:53 +0200)
Remove the timestamp passed for ratelimit checks. Let the limit
calculation obtain a timestamp when it needs it. Most transfers run
without active ratelimits and getting a fresh timestamp is unnecessary.

Closes #22292

lib/http2.c
lib/multi.c
lib/progress.c
lib/ratelimit.c
lib/ratelimit.h
lib/sendf.c
lib/transfer.c
lib/vquic/cf-ngtcp2-proxy.c
lib/vquic/cf-ngtcp2.c
tests/http/scorecard.py

index a820439ef45a3ef9e35bdcd2da40d12c8a1f2722..ff3d3d2741fb6dc156dc35ae3c3fcf90ff08cd76 100644 (file)
@@ -284,8 +284,7 @@ static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx)
 static int32_t cf_h2_get_desired_local_win(struct Curl_cfilter *cf,
                                            struct Curl_easy *data)
 {
-  curl_off_t avail = Curl_rlimit_avail(&data->progress.dl.rlimit,
-                                       Curl_pgrs_now(data));
+  curl_off_t avail = Curl_rlimit_avail(&data->progress.dl.rlimit, NULL);
 
   (void)cf;
   if(avail < CURL_OFF_T_MAX) { /* limit in place */
index d65c48e2657b16c6a71226e00fc177133136c234..7d0bc0a125c65eeb4a50c0f4d75a2cf46e37d353 100644 (file)
@@ -994,11 +994,10 @@ static CURLcode multi_adjust_pollset(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
 
   if(ps->n) {
-    const struct curltime *pnow = Curl_pgrs_now(data);
     bool send_blocked, recv_blocked;
 
-    recv_blocked = (Curl_rlimit_avail(&data->progress.dl.rlimit, pnow) <= 0);
-    send_blocked = (Curl_rlimit_avail(&data->progress.ul.rlimit, pnow) <= 0);
+    recv_blocked = (Curl_rlimit_avail(&data->progress.dl.rlimit, NULL) <= 0);
+    send_blocked = (Curl_rlimit_avail(&data->progress.ul.rlimit, NULL) <= 0);
     if(send_blocked || recv_blocked) {
       int i;
       for(i = 0; i <= SECONDARYSOCKET; ++i) {
index 3b3642b9a0b697dbb60b90eb39fc9369b529ffe3..72d03edf2de8ba730281bcba97120da6879db35f 100644 (file)
@@ -172,10 +172,8 @@ UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data,
 
 const struct curltime *Curl_pgrs_now(struct Curl_easy *data)
 {
-  struct curltime *pnow = data->multi ?
-                          &data->multi->now : &data->progress.now;
-  curlx_pnow(pnow);
-  return pnow;
+  curlx_pnow(&data->progress.now);
+  return &data->progress.now;
 }
 
 /*
@@ -392,7 +390,7 @@ void Curl_pgrs_download_inc(struct Curl_easy *data, size_t delta)
 {
   if(delta) {
     data->progress.dl.cur_size += delta;
-    Curl_rlimit_drain(&data->progress.dl.rlimit, delta, Curl_pgrs_now(data));
+    Curl_rlimit_drain(&data->progress.dl.rlimit, delta, NULL);
   }
 }
 
@@ -400,7 +398,7 @@ void Curl_pgrs_upload_inc(struct Curl_easy *data, size_t delta)
 {
   if(delta) {
     data->progress.ul.cur_size += delta;
-    Curl_rlimit_drain(&data->progress.ul.rlimit, delta, Curl_pgrs_now(data));
+    Curl_rlimit_drain(&data->progress.ul.rlimit, delta, NULL);
   }
 }
 
index 97af01c78801cf32ad30e0d4f32fb2650ccc4d6b..a5efc7c11a3851fbdb694d2b388a296e849bf19e 100644 (file)
@@ -200,9 +200,15 @@ bool Curl_rlimit_is_blocked(struct Curl_rlimit *r)
 int64_t Curl_rlimit_avail(struct Curl_rlimit *r,
                           const struct curltime *pts)
 {
+  struct curltime ts;
+
   if(r->blocked)
     return 0;
   else if(r->rate_per_step) {
+    if(!pts) {
+      curlx_pnow(&ts);
+      pts = &ts;
+    }
     rlimit_update(r, pts);
     return r->tokens;
   }
@@ -210,13 +216,18 @@ int64_t Curl_rlimit_avail(struct Curl_rlimit *r,
     return INT64_MAX;
 }
 
-void Curl_rlimit_drain(struct Curl_rlimit *r,
-                       size_t tokens,
+void Curl_rlimit_drain(struct Curl_rlimit *r, size_t tokens,
                        const struct curltime *pts)
 {
+  struct curltime ts;
+
   if(r->blocked || !r->rate_per_step)
     return;
 
+  if(!pts) {
+    curlx_pnow(&ts);
+    pts = &ts;
+  }
   rlimit_update(r, pts);
 #if 8 <= SIZEOF_SIZE_T
   if(tokens > INT64_MAX) {
index 3c3e38b89587283b7db21e2257f4dac0f41f8c06..3548f55608ff0e886c962e6b9d36f923047f3fdb 100644 (file)
@@ -90,14 +90,15 @@ bool Curl_rlimit_active(struct Curl_rlimit *r);
 bool Curl_rlimit_is_blocked(struct Curl_rlimit *r);
 int64_t Curl_rlimit_per_step(struct Curl_rlimit *r);
 
-/* Return how many tokens are available to spend, may be negative */
+/* Return how many tokens are available to spend, may be negative.
+ * Pass timestamp or NULL. */
 int64_t Curl_rlimit_avail(struct Curl_rlimit *r,
                           const struct curltime *pts);
 
 /* Drain tokens from the ratelimit, give an estimate of how many tokens
- * remain to be drained in the future (-1 for unknown). */
-void Curl_rlimit_drain(struct Curl_rlimit *r,
-                       size_t tokens,
+ * remain to be drained in the future (-1 for unknown).
+ * Pass timestamp or NULL. */
+void Curl_rlimit_drain(struct Curl_rlimit *r, size_t tokens,
                        const struct curltime *pts);
 
 /* Block/unblock ratelimiting. A blocked ratelimit has 0 tokens available. */
index b830995345bed8c3a0de9799370ae1fb4cff2be9..efaba08eb4cad5c416af2703d476866f5b1610a2 100644 (file)
@@ -1239,8 +1239,7 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
   }
 
   if(Curl_rlimit_active(&data->progress.ul.rlimit)) {
-    curl_off_t ul_avail = Curl_rlimit_avail(&data->progress.ul.rlimit,
-                                            Curl_pgrs_now(data));
+    curl_off_t ul_avail = Curl_rlimit_avail(&data->progress.ul.rlimit, NULL);
     if(ul_avail <= 0) {
       result = CURLE_OK;
       *eos = FALSE;
index 11d36ac427215a5882cdd379f1cea38f9c2211b1..2eab7cabad4c823afee18b4566941f9ba5585987 100644 (file)
@@ -250,8 +250,7 @@ static CURLcode sendrecv_dl(struct Curl_easy *data,
     bytestoread = xfer_blen;
 
     if(bytestoread && Curl_rlimit_active(&data->progress.dl.rlimit)) {
-      curl_off_t dl_avail = Curl_rlimit_avail(&data->progress.dl.rlimit,
-                                              Curl_pgrs_now(data));
+      curl_off_t dl_avail = Curl_rlimit_avail(&data->progress.dl.rlimit, NULL);
 #if 0
       DEBUGF(infof(data, "dl_rlimit, available=%" FMT_OFF_T, dl_avail));
 #endif
index 7a7fe417c38a0a0bf0529f53f253bc6c0b27994b..9a43a443cc9edfee210ef0c88e695680b440ad02 100644 (file)
@@ -281,7 +281,7 @@ static void cf_h3_proxy_upd_rx_win(struct Curl_cfilter *cf,
     if(!stream->rx_offset)
       return;
 
-    avail = Curl_rlimit_avail(&data->progress.dl.rlimit, Curl_pgrs_now(data));
+    avail = Curl_rlimit_avail(&data->progress.dl.rlimit, NULL);
     if(avail <= 0) {
       /* nothing available, do not extend the rx offset */
       CURL_TRC_CF(data, cf, "[%" PRId64 "] dl rate limit exhausted (%" PRId64
index f03ec06a4506149fd9cf5fec032ea5d870d062a7..9a905a745a462fe7a25c86af7cbf81dc54f71245 100644 (file)
@@ -175,7 +175,7 @@ static void cf_ngtcp2_upd_rx_win(struct Curl_cfilter *cf,
     if(!stream->rx_offset)
       return;
 
-    avail = Curl_rlimit_avail(&data->progress.dl.rlimit, Curl_pgrs_now(data));
+    avail = Curl_rlimit_avail(&data->progress.dl.rlimit, NULL);
     if(avail <= 0) {
       /* nothing available, do not extend the rx offset */
       CURL_TRC_CF(data, cf, "[%" PRId64 "] dl rate limit exhausted (%" PRId64
index 36947592e28c4d32be30b3aae7883801cc2e4d3f..2a45450aa40d6c8ebb3311ae6c4d57320e803c23 100644 (file)
@@ -71,6 +71,8 @@ class Card:
     def fmt_mbs(cls, val):
         if val is None or val < 0:
             return '--'
+        if val >= (1024 * 1024 * 1024):
+            return f'{val / (1024 * 1024 * 1024):.3g} GB/s'
         if val >= (1024 * 1024):
             return f'{val / (1024 * 1024):.3g} MB/s'
         if val >= 1024: