The old rate-limitation logic paused for 1 second.  The attached patch 
calculates
a better timeout based on requested speed and buffer size.  I believe this will
give smoother rate limitation performance.

Please note that at very slow speeds, you need to use small-ish buffer sizes to 
get good smoothing.

This patch is on top of my previous patches.  It fixes a few compiler warnings
as well.

Please let me know if it needs any improvements to make it more acceptable.

Thanks,
Ben

--
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com

diff --git a/lib/tftp.c b/lib/tftp.c
index 0c9b069..203581e 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -268,7 +268,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
     state->retry_max=50;
 
   /* Compute the re-ACK interval to suit the timeout */
-  state->retry_time = timeout/state->retry_max;
+  state->retry_time = (int)(timeout/state->retry_max);
   if(state->retry_time<1)
     state->retry_time=1;
 
@@ -1177,33 +1177,6 @@ static long tftp_state_timeout(struct connectdata *conn, 
tftp_event_t *event)
   }
 }
 
-static curl_off_t sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
-                             int pkt_size)
-{
-  curl_off_t min_sleep = 0;
-  curl_off_t rv = 0;
-
-  if (rate_bps == 0)
-    return 0;
-
-  if (cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
-    /* running too fast */
-    rate_bps -= rate_bps >> 6;
-    min_sleep = 1;
-  }
-  else if (cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
-    /* running too slow */
-    rate_bps += rate_bps >> 6;
-  }
-
-  rv = ((curl_off_t)((pkt_size * 8) * 1000) / rate_bps);
-
-  if (rv < min_sleep)
-    rv = min_sleep;
-
-  return rv;
-}
-
 
 /**********************************************************
  *
@@ -1236,8 +1209,8 @@ static CURLcode tftp_easy_statemach(struct connectdata 
*conn)
       if (data->set.max_send_speed &&
           (data->progress.ulspeed > data->set.max_send_speed)) {
         fd_read = CURL_SOCKET_BAD;
-        timeout_ms = sleep_time(data->set.max_send_speed,
-                                data->progress.ulspeed, state->blksize);
+        timeout_ms = Curl_sleep_time(data->set.max_send_speed,
+                                     data->progress.ulspeed, state->blksize);
       }
       else {
         fd_read = state->sockfd;
@@ -1247,8 +1220,8 @@ static CURLcode tftp_easy_statemach(struct connectdata 
*conn)
       if (data->set.max_recv_speed &&
           (data->progress.dlspeed > data->set.max_recv_speed)) {
         fd_read = CURL_SOCKET_BAD;
-        timeout_ms = sleep_time(data->set.max_recv_speed,
-                                data->progress.dlspeed, state->blksize);
+        timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
+                                     data->progress.dlspeed, state->blksize);
       }
       else {
         fd_read = state->sockfd;
@@ -1265,7 +1238,7 @@ static CURLcode tftp_easy_statemach(struct connectdata 
*conn)
 
 
     /* Wait until ready to read or timeout occurs */
-    rc=Curl_socket_ready(fd_read, CURL_SOCKET_BAD, timeout_ms);
+    rc = Curl_socket_ready(fd_read, CURL_SOCKET_BAD, (int)(timeout_ms));
 
     k->now = Curl_tvnow();
 
diff --git a/lib/transfer.c b/lib/transfer.c
index b6b2cf6..672d424 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1176,6 +1176,34 @@ int Curl_single_getsock(const struct connectdata *conn,
 }
 
 
+curl_off_t Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+                             int pkt_size)
+{
+  curl_off_t min_sleep = 0;
+  curl_off_t rv = 0;
+
+  if (rate_bps == 0)
+    return 0;
+
+  if (cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
+    /* running too fast */
+    rate_bps -= rate_bps >> 6;
+    min_sleep = 1;
+  }
+  else if (cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
+    /* running too slow */
+    rate_bps += rate_bps >> 6;
+  }
+
+  rv = ((curl_off_t)((pkt_size * 8) * 1000) / rate_bps);
+
+  if (rv < min_sleep)
+    rv = min_sleep;
+
+  return rv;
+}
+
+
 /*
  * Transfer()
  *
@@ -1197,6 +1225,8 @@ Transfer(struct connectdata *conn)
   bool done=FALSE;
   bool first=TRUE;
   int timeout_ms;
+  int buffersize;
+  int totmp;
 
   if((conn->sockfd == CURL_SOCKET_BAD) &&
      (conn->writesockfd == CURL_SOCKET_BAD))
@@ -1211,6 +1241,7 @@ Transfer(struct connectdata *conn)
     curl_socket_t fd_read = conn->sockfd;
     curl_socket_t fd_write = conn->writesockfd;
     int keepon = k->keepon;
+    timeout_ms = 1000;
 
     if(conn->waitfor) {
       /* if waitfor is set, get the RECV and SEND bits from that but keep the
@@ -1228,6 +1259,16 @@ Transfer(struct connectdata *conn)
       k->keepon &= ~KEEP_SEND_HOLD;
     }
     else {
+      if (data->set.upload && data->set.max_send_speed &&
+          (data->progress.ulspeed > data->set.max_send_speed) ) {
+        /* calculate upload rate-limitation timeout. */
+        buffersize = (int)(data->set.buffer_size ?
+                           data->set.buffer_size : BUFSIZE);
+        totmp = (int)Curl_sleep_time(data->set.max_send_speed,
+                                     data->progress.ulspeed, buffersize);
+        if (totmp < timeout_ms)
+          timeout_ms = totmp;
+      }
       fd_write = CURL_SOCKET_BAD;
       if(keepon & KEEP_SEND)
         k->keepon |= KEEP_SEND_HOLD; /* hold it */
@@ -1239,6 +1280,16 @@ Transfer(struct connectdata *conn)
       k->keepon &= ~KEEP_RECV_HOLD;
     }
     else {
+      if ((!data->set.upload) && data->set.max_recv_speed &&
+          (data->progress.dlspeed > data->set.max_recv_speed)) {
+        /* Calculate download rate-limitation timeout. */
+        buffersize = (int)(data->set.buffer_size ?
+                           data->set.buffer_size : BUFSIZE);
+        totmp = (int)Curl_sleep_time(data->set.max_recv_speed,
+                                     data->progress.dlspeed, buffersize);
+        if (totmp < timeout_ms)
+          timeout_ms = totmp;
+      }
       fd_read = CURL_SOCKET_BAD;
       if(keepon & KEEP_RECV)
         k->keepon |= KEEP_RECV_HOLD; /* hold it */
@@ -1267,14 +1318,15 @@ Transfer(struct connectdata *conn)
       timeout_ms = 0;
     else {
       if(data->set.timeout) {
-        timeout_ms = data->set.timeout - Curl_tvdiff(k->now, k->start);
-        if(timeout_ms > 1000)
-          timeout_ms = 1000;
-        else if(timeout_ms < 0)
+        totmp = (int)(data->set.timeout - Curl_tvdiff(k->now, k->start));
+        if(totmp < 0)
           return CURLE_OPERATION_TIMEDOUT;
       }
       else
-        timeout_ms = 1000;
+        totmp = 1000;
+
+      if (totmp < timeout_ms)
+        timeout_ms = totmp;
     }
 
     switch (Curl_socket_ready(fd_read, fd_write, timeout_ms)) {
diff --git a/lib/transfer.h b/lib/transfer.h
index 248b627..e404959 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -61,4 +61,8 @@ Curl_setup_transfer (struct connectdata *data,
                                            -1 disables */
                curl_off_t *writecountp /* return number of bytes written */
 );
+
+curl_off_t Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+                           int pkt_size);
+
 #endif
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to