Please find attached... The quick test:
If you run wget with --limit-percent 50, you should see it run at full blast for 15 seconds and then back off till it's downloading at 50% the rate it acheived in the first 15 seconds. This is only the initial Works For Me version of the patch. Comments welcome, as anyone else who wants to run with it is welcome to do so. Best Regards. Tony PS to Micah: Yes, I changed pct to percent.
diff --git a/src/init.c b/src/init.c --- a/src/init.c +++ b/src/init.c @@ -179,6 +179,7 @@ static const struct { #endif { "input", &opt.input_filename, cmd_file }, { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean }, + { "limitpercent", &opt.limit_percent, cmd_number }, { "limitrate", &opt.limit_rate, cmd_bytes }, { "loadcookies", &opt.cookies_input, cmd_file }, { "logfile", &opt.lfilename, cmd_file }, diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -189,6 +189,7 @@ static struct cmdline_option option_data { "input-file", 'i', OPT_VALUE, "input", -1 }, { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 }, { "level", 'l', OPT_VALUE, "reclevel", -1 }, + { "limit-percent", 0, OPT_VALUE, "limitpercent", -1 }, { "limit-rate", 0, OPT_VALUE, "limitrate", -1 }, { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 }, { "max-redirect", 0, OPT_VALUE, "maxredirect", -1 }, @@ -453,6 +454,10 @@ Download:\n"), -Q, --quota=NUMBER set retrieval quota to NUMBER.\n"), N_("\ --bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host.\n"), + N_("\ + --limit-percent=NUMBER limit download rate to NUMBER percent of measured initial burst\n"), + N_("\ + or rate specified by --limit-rate\n"), N_("\ --limit-rate=RATE limit download rate to RATE.\n"), N_("\ diff --git a/src/options.h b/src/options.h --- a/src/options.h +++ b/src/options.h @@ -115,6 +115,8 @@ struct options double waitretry; /* The wait period between retries. - HEH */ bool use_robots; /* Do we heed robots.txt? */ + wgint limit_percent; /* Limit the download rate to this percentage + of initial measured burst rate. */ wgint limit_rate; /* Limit the download rate to this many bps. */ SUM_SIZE_INT quota; /* Maximum file size to download and diff --git a/src/retr.c b/src/retr.c --- a/src/retr.c +++ b/src/retr.c @@ -86,14 +86,61 @@ limit_bandwidth (wgint bytes, struct pti limit_bandwidth (wgint bytes, struct ptimer *timer) { double delta_t = ptimer_read (timer) - limit_data.chunk_start; - double expected; + double expected= 0.0; limit_data.chunk_bytes += bytes; + static wgint measured_limit= 0; + + wgint limit= 0; + + if ( opt.limit_rate ) + { + limit= opt.limit_rate; + + if ( opt.limit_percent ) + { + limit= limit * opt.limit_percent / 100; + } + DEBUGP(("fixed limit governs: %lld bps\n", limit)); + } + else + if ( opt.limit_percent ) + { + if ( ! measured_limit ) + { + static double total_sec= 0.0; + static wgint total_bytes= 0; + + total_sec += delta_t; + total_bytes += bytes; + const double MEASURE_SEC= 15.0; + + if ( total_sec > MEASURE_SEC ) + { + DEBUGP(("After %.3f seconds we saw %lld bytes so our measured limit is %lld bps\n", + total_sec / 1000, total_bytes, measured_limit )); + measured_limit = total_bytes / total_sec * opt.limit_percent / 100.0; + } + } + + if ( measured_limit ) + { + if ( !limit || measured_limit < limit ) + { + limit= measured_limit; + } + } + } + + if ( limit ) + { + /* Calculate the amount of time we expect downloading the chunk - should take. If in reality it took less time, sleep to - compensate for the difference. */ - expected = (double) limit_data.chunk_bytes / opt.limit_rate; + should take at this fixed rate. If in reality it took less time, + sleep to compensate for the difference. */ + + expected = (double) limit_data.chunk_bytes / limit; if (expected > delta_t) { @@ -127,6 +174,8 @@ limit_bandwidth (wgint bytes, struct pti limit_data.sleep_adjust = -0.5; } + } + limit_data.chunk_bytes = 0; limit_data.chunk_start = ptimer_read (timer); } @@ -229,13 +278,13 @@ fd_read_body (int fd, FILE *out, wgint t progress_interactive = progress_interactive_p (progress); } - if (opt.limit_rate) + if (opt.limit_rate || opt.limit_percent) limit_bandwidth_reset (); /* A timer is needed for tracking progress, for throttling, and for tracking elapsed time. If either of these are requested, start the timer. */ - if (progress || opt.limit_rate || elapsed) + if (progress || opt.limit_rate || opt.limit_percent || elapsed) { timer = ptimer_new (); last_successful_read_tm = 0; @@ -286,7 +335,7 @@ fd_read_body (int fd, FILE *out, wgint t else if (ret <= 0) break; /* EOF or read error */ - if (progress || opt.limit_rate) + if (progress || opt.limit_rate || opt.limit_percent) { ptimer_measure (timer); if (ret > 0) @@ -303,7 +352,7 @@ fd_read_body (int fd, FILE *out, wgint t } } - if (opt.limit_rate) + if (opt.limit_rate || opt.limit_percent) limit_bandwidth (ret, timer); if (progress)