summaryrefslogtreecommitdiff
path: root/lib/multi.c
diff options
context:
space:
mode:
authorOlivier Brunel <jjk@jjacky.com>2016-08-16 20:32:02 +0200
committerDaniel Stenberg <daniel@haxx.se>2016-09-04 13:11:23 +0200
commit4b86113f5ed66270364738a351ebb5bb23cd0882 (patch)
tree46e47059805dc88774d9a29e5210c6496e031c37 /lib/multi.c
parent85e5ebe75f8432333a53832d7acd0ebd65ae2506 (diff)
downloadgnurl-4b86113f5ed66270364738a351ebb5bb23cd0882.tar.gz
gnurl-4b86113f5ed66270364738a351ebb5bb23cd0882.tar.bz2
gnurl-4b86113f5ed66270364738a351ebb5bb23cd0882.zip
speed caps: not based on average speeds anymore
Speed limits (from CURLOPT_MAX_RECV_SPEED_LARGE & CURLOPT_MAX_SEND_SPEED_LARGE) were applied simply by comparing limits with the cumulative average speed of the entire transfer; While this might work at times with good/constant connections, in other cases it can result to the limits simply being "ignored" for more than "short bursts" (as told in man page). Consider a download that goes on much slower than the limit for some time (because bandwidth is used elsewhere, server is slow, whatever the reason), then once things get better, curl would simply ignore the limit up until the average speed (since the beginning of the transfer) reached the limit. This could prove the limit useless to effectively avoid using the entire bandwidth (at least for quite some time). So instead, we now use a "moving starting point" as reference, and every time at least as much as the limit as been transferred, we can reset this starting point to the current position. This gets a good limiting effect that applies to the "current speed" with instant reactivity (in case of sudden speed burst). Closes #971
Diffstat (limited to 'lib/multi.c')
-rw-r--r--lib/multi.c60
1 files changed, 32 insertions, 28 deletions
diff --git a/lib/multi.c b/lib/multi.c
index e1325f029..8e4091687 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1801,9 +1801,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = Curl_speedcheck(data, now);
if(( (data->set.max_send_speed == 0) ||
- (data->progress.ulspeed < data->set.max_send_speed)) &&
+ (Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now) <= 0)) &&
( (data->set.max_recv_speed == 0) ||
- (data->progress.dlspeed < data->set.max_recv_speed)))
+ (Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now) <= 0)))
multistate(data, CURLM_STATE_PERFORM);
break;
@@ -1814,35 +1822,31 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
bool comeback = FALSE;
/* check if over send speed */
- if((data->set.max_send_speed > 0) &&
- (data->progress.ulspeed > data->set.max_send_speed)) {
- int buffersize;
-
- multistate(data, CURLM_STATE_TOOFAST);
-
- /* calculate upload rate-limitation timeout. */
- buffersize = (int)(data->set.buffer_size ?
- data->set.buffer_size : BUFSIZE);
- timeout_ms = Curl_sleep_time(data->set.max_send_speed,
- data->progress.ulspeed, buffersize);
- Curl_expire_latest(data, timeout_ms);
- break;
+ if(data->set.max_send_speed > 0) {
+ timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
+ if(timeout_ms > 0) {
+ multistate(data, CURLM_STATE_TOOFAST);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
}
/* check if over recv speed */
- if((data->set.max_recv_speed > 0) &&
- (data->progress.dlspeed > data->set.max_recv_speed)) {
- int buffersize;
-
- multistate(data, CURLM_STATE_TOOFAST);
-
- /* Calculate download rate-limitation timeout. */
- buffersize = (int)(data->set.buffer_size ?
- data->set.buffer_size : BUFSIZE);
- timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
- data->progress.dlspeed, buffersize);
- Curl_expire_latest(data, timeout_ms);
- break;
+ if(data->set.max_recv_speed > 0) {
+ timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+ if(timeout_ms > 0) {
+ multistate(data, CURLM_STATE_TOOFAST);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
}
/* read/write data if it is ready to do so */