rate-limit: use three second window to better handle high speeds

Due to very frequent updates of the rate limit "window", it could
attempt to rate limit within the same milliseconds and that then made
the calculations wrong, leading to it not behaving correctly on very
fast transfers.

This new logic updates the rate limit "window" to be no shorter than the
last three seconds and only updating the timestamps for this when
switching between the states TOOFAST/PERFORM.

Reported-by: 刘佩东
Fixes #2386
Closes #2388
This commit is contained in:
Daniel Stenberg 2018-03-15 16:43:00 +01:00
parent 236402fc2d
commit f5700ea88b
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 61 additions and 43 deletions

View file

@ -1823,22 +1823,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now);
send_timeout_ms =
Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now);
recv_timeout_ms =
Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now);
if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
Curl_ratelimit(data, now);
}
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
@ -1870,7 +1874,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_start,
now);
if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
if(send_timeout_ms || recv_timeout_ms) {
Curl_ratelimit(data, now);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);