multi: process pending, one by one

Before curl 8.14.0, when pending was a list, `process_pending_handles()`
move a single transfer to processing. In 8.14.0 we changed that to move
all pending transfers to processing. This lead to unwanted performance
drops as reported in #18017.

Restore the old behaviour.

While the old behviour is better, the overall handling of "pending"
transfers is not optimal, since we do not keep track of the "condition"
a pending transfer is waiting on. This means, when moving a single,
pending transfer, we might move one that still cannot be processed while
another that could is kept pending.

Since we trigger `process_pending_handles()` from various changes, the
stalled pending will eventually make it to the processing queue, but
this is not optimal.

Fixes #18017
Reported-by: rm-rmonaghan on github
Closes #18056
This commit is contained in:
Stefan Eissing 2025-07-28 11:37:26 +02:00 committed by Daniel Stenberg
parent 9d2075bdce
commit 85e18a5b9a
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -3672,9 +3672,13 @@ static void process_pending_handles(struct Curl_multi *multi)
if(Curl_uint_bset_first(&multi->pending, &mid)) {
do {
struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
DEBUGASSERT(data);
if(data)
if(data) {
move_pending_to_connect(multi, data);
break;
}
/* transfer no longer known, should not happen */
Curl_uint_bset_remove(&multi->pending, mid);
DEBUGASSERT(0);
}
while(Curl_uint_bset_next(&multi->pending, mid, &mid));
}