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
This commit is contained in:
Stefan Eissing 2026-07-10 11:47:48 +02:00 committed by Daniel Stenberg
parent c3ae9ef822
commit 34bc5b60bc
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
10 changed files with 31 additions and 23 deletions

View 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 */

View 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) {

View 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);
}
}

View 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) {

View 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. */

View 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;

View 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

View 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

View 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

View 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: