From: Stefan Eissing Date: Fri, 10 Jul 2026 09:47:48 +0000 (+0200) Subject: lib: ratelimit timestamps X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=34bc5b60bcc13b413116c7eb3635c202ad02f206;p=thirdparty%2Fcurl.git lib: ratelimit timestamps 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 --- diff --git a/lib/http2.c b/lib/http2.c index a820439ef4..ff3d3d2741 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -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 */ diff --git a/lib/multi.c b/lib/multi.c index d65c48e265..7d0bc0a125 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -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) { diff --git a/lib/progress.c b/lib/progress.c index 3b3642b9a0..72d03edf2d 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -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); } } diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 97af01c788..a5efc7c11a 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c @@ -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) { diff --git a/lib/ratelimit.h b/lib/ratelimit.h index 3c3e38b895..3548f55608 100644 --- a/lib/ratelimit.h +++ b/lib/ratelimit.h @@ -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. */ diff --git a/lib/sendf.c b/lib/sendf.c index b830995345..efaba08eb4 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -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; diff --git a/lib/transfer.c b/lib/transfer.c index 11d36ac427..2eab7cabad 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -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 diff --git a/lib/vquic/cf-ngtcp2-proxy.c b/lib/vquic/cf-ngtcp2-proxy.c index 7a7fe417c3..9a43a443cc 100644 --- a/lib/vquic/cf-ngtcp2-proxy.c +++ b/lib/vquic/cf-ngtcp2-proxy.c @@ -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 diff --git a/lib/vquic/cf-ngtcp2.c b/lib/vquic/cf-ngtcp2.c index f03ec06a45..9a905a745a 100644 --- a/lib/vquic/cf-ngtcp2.c +++ b/lib/vquic/cf-ngtcp2.c @@ -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 diff --git a/tests/http/scorecard.py b/tests/http/scorecard.py index 36947592e2..2a45450aa4 100644 --- a/tests/http/scorecard.py +++ b/tests/http/scorecard.py @@ -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: