mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Make timers measure seconds directly, not milliseconds.
This commit is contained in:
parent
bfbd0d35e9
commit
3d5863424b
@ -1,3 +1,8 @@
|
|||||||
|
2005-07-06 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* ptimer.c: Measure time in seconds rather than milliseconds.
|
||||||
|
Adjusted all callers.
|
||||||
|
|
||||||
2005-07-06 Hrvoje Niksic <hniksic@xemacs.org>
|
2005-07-06 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* http.c (gethttp): When freeing MESSAGE, take into account that
|
* http.c (gethttp): When freeing MESSAGE, take into account that
|
||||||
|
@ -166,7 +166,7 @@ convert_all_links (void)
|
|||||||
free_urlpos (urls);
|
free_urlpos (urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
secs = ptimer_measure (timer) / 1000;
|
secs = ptimer_measure (timer);
|
||||||
ptimer_destroy (timer);
|
ptimer_destroy (timer);
|
||||||
logprintf (LOG_VERBOSE, _("Converted %d files in %s seconds.\n"),
|
logprintf (LOG_VERBOSE, _("Converted %d files in %s seconds.\n"),
|
||||||
file_count, print_decimal (secs));
|
file_count, print_decimal (secs));
|
||||||
|
@ -974,7 +974,7 @@ Can't timestamp and not clobber old files at the same time.\n"));
|
|||||||
time_str (NULL),
|
time_str (NULL),
|
||||||
opt.numurls,
|
opt.numurls,
|
||||||
human_readable (total_downloaded_bytes),
|
human_readable (total_downloaded_bytes),
|
||||||
secs_to_human_time (total_download_time / 1000),
|
secs_to_human_time (total_download_time),
|
||||||
retr_rate (total_downloaded_bytes, total_download_time));
|
retr_rate (total_downloaded_bytes, total_download_time));
|
||||||
/* Print quota warning, if exceeded. */
|
/* Print quota warning, if exceeded. */
|
||||||
if (opt.quota && total_downloaded_bytes > opt.quota)
|
if (opt.quota && total_downloaded_bytes > opt.quota)
|
||||||
|
@ -175,7 +175,7 @@ progress_interactive_p (void *progress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Inform the progress gauge of newly received bytes. DLTIME is the
|
/* Inform the progress gauge of newly received bytes. DLTIME is the
|
||||||
time in milliseconds since the beginning of the download. */
|
time since the beginning of the download. */
|
||||||
|
|
||||||
void
|
void
|
||||||
progress_update (void *progress, wgint howmuch, double dltime)
|
progress_update (void *progress, wgint howmuch, double dltime)
|
||||||
@ -320,20 +320,18 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last)
|
|||||||
wgint bytes_remaining = dp->total_length - bytes_displayed;
|
wgint bytes_remaining = dp->total_length - bytes_displayed;
|
||||||
/* The quantity downloaded in this download run. */
|
/* The quantity downloaded in this download run. */
|
||||||
wgint bytes_sofar = bytes_displayed - dp->initial_length;
|
wgint bytes_sofar = bytes_displayed - dp->initial_length;
|
||||||
double secs_sofar = dltime / 1000;
|
int eta = (int) (dltime * bytes_remaining / bytes_sofar + 0.5);
|
||||||
int eta = (int) (secs_sofar * bytes_remaining / bytes_sofar + 0.5);
|
|
||||||
logprintf (LOG_VERBOSE, " %s", eta_to_human_short (eta, true));
|
logprintf (LOG_VERBOSE, " %s", eta_to_human_short (eta, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* When done, print the total download time */
|
/* When done, print the total download time */
|
||||||
double secs = dltime / 1000;
|
if (dltime >= 10)
|
||||||
if (secs >= 10)
|
|
||||||
logprintf (LOG_VERBOSE, "=%s",
|
logprintf (LOG_VERBOSE, "=%s",
|
||||||
eta_to_human_short ((int) (secs + 0.5), true));
|
eta_to_human_short ((int) (dltime + 0.5), true));
|
||||||
else
|
else
|
||||||
logprintf (LOG_VERBOSE, "=%ss", print_decimal (secs));
|
logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,12 +476,12 @@ static volatile sig_atomic_t received_sigwinch;
|
|||||||
sample is at least 150ms long, which means that, over the course of
|
sample is at least 150ms long, which means that, over the course of
|
||||||
20 samples, "current" download speed spans at least 3s into the
|
20 samples, "current" download speed spans at least 3s into the
|
||||||
past. */
|
past. */
|
||||||
#define DLSPEED_SAMPLE_MIN 150
|
#define DLSPEED_SAMPLE_MIN 0.15
|
||||||
|
|
||||||
/* The time after which the download starts to be considered
|
/* The time after which the download starts to be considered
|
||||||
"stalled", i.e. the current bandwidth is not printed and the recent
|
"stalled", i.e. the current bandwidth is not printed and the recent
|
||||||
download speeds are scratched. */
|
download speeds are scratched. */
|
||||||
#define STALL_START_TIME 5000
|
#define STALL_START_TIME 5
|
||||||
|
|
||||||
struct bar_progress {
|
struct bar_progress {
|
||||||
wgint initial_length; /* how many bytes have been downloaded
|
wgint initial_length; /* how many bytes have been downloaded
|
||||||
@ -513,12 +511,12 @@ struct bar_progress {
|
|||||||
details. */
|
details. */
|
||||||
struct bar_progress_hist {
|
struct bar_progress_hist {
|
||||||
int pos;
|
int pos;
|
||||||
wgint times[DLSPEED_HISTORY_SIZE];
|
double times[DLSPEED_HISTORY_SIZE];
|
||||||
wgint bytes[DLSPEED_HISTORY_SIZE];
|
wgint bytes[DLSPEED_HISTORY_SIZE];
|
||||||
|
|
||||||
/* The sum of times and bytes respectively, maintained for
|
/* The sum of times and bytes respectively, maintained for
|
||||||
efficiency. */
|
efficiency. */
|
||||||
wgint total_time;
|
double total_time;
|
||||||
wgint total_bytes;
|
wgint total_bytes;
|
||||||
} hist;
|
} hist;
|
||||||
|
|
||||||
@ -618,7 +616,7 @@ bar_update (void *progress, wgint howmuch, double dltime)
|
|||||||
received_sigwinch = 0;
|
received_sigwinch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dltime - bp->last_screen_update < 200 && !force_screen_update)
|
if (dltime - bp->last_screen_update < 0.2 && !force_screen_update)
|
||||||
/* Don't update more often than five times per second. */
|
/* Don't update more often than five times per second. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -708,7 +706,7 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime)
|
|||||||
value because the current bandwidth would start too small.
|
value because the current bandwidth would start too small.
|
||||||
Start with an arbitrary (but more reasonable) time value and
|
Start with an arbitrary (but more reasonable) time value and
|
||||||
let it level out. */
|
let it level out. */
|
||||||
recent_age = 1000;
|
recent_age = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store "recent" bytes and download time to history ring at the
|
/* Store "recent" bytes and download time to history ring at the
|
||||||
@ -743,8 +741,14 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime)
|
|||||||
sumt += hist->times[i];
|
sumt += hist->times[i];
|
||||||
sumb += hist->bytes[i];
|
sumb += hist->bytes[i];
|
||||||
}
|
}
|
||||||
assert (sumt == hist->total_time);
|
|
||||||
assert (sumb == hist->total_bytes);
|
assert (sumb == hist->total_bytes);
|
||||||
|
/* We can't use assert(sumt==hist->total_time) because some
|
||||||
|
precision is lost by adding and subtracting floating-point
|
||||||
|
numbers. But during a download this precision should not be
|
||||||
|
detectable, i.e. no larger than 1ns. */
|
||||||
|
double diff = sumt - hist->total_time;
|
||||||
|
if (diff < 0) diff = -diff;
|
||||||
|
assert (diff < 1e-9);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -879,7 +883,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
|||||||
move_to_end (p);
|
move_to_end (p);
|
||||||
|
|
||||||
/* " 12.52K/s" */
|
/* " 12.52K/s" */
|
||||||
if (hist->total_time && hist->total_bytes)
|
if (hist->total_time > 0 && hist->total_bytes)
|
||||||
{
|
{
|
||||||
static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
|
static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
|
||||||
int units = 0;
|
int units = 0;
|
||||||
@ -900,7 +904,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
|||||||
/* " eta ..m ..s"; wait for three seconds before displaying the ETA.
|
/* " eta ..m ..s"; wait for three seconds before displaying the ETA.
|
||||||
That's because the ETA value needs a while to become
|
That's because the ETA value needs a while to become
|
||||||
reliable. */
|
reliable. */
|
||||||
if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3000)
|
if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3)
|
||||||
{
|
{
|
||||||
int eta;
|
int eta;
|
||||||
|
|
||||||
@ -909,7 +913,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
|||||||
any value to the user. */
|
any value to the user. */
|
||||||
if (bp->total_length != size
|
if (bp->total_length != size
|
||||||
&& bp->last_eta_value != 0
|
&& bp->last_eta_value != 0
|
||||||
&& dl_total_time - bp->last_eta_time < 900)
|
&& dl_total_time - bp->last_eta_time < 0.9)
|
||||||
eta = bp->last_eta_value;
|
eta = bp->last_eta_value;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -919,9 +923,8 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
|||||||
hist->total_time and bp->count with hist->total_bytes.
|
hist->total_time and bp->count with hist->total_bytes.
|
||||||
I found that doing that results in a very jerky and
|
I found that doing that results in a very jerky and
|
||||||
ultimately unreliable ETA. */
|
ultimately unreliable ETA. */
|
||||||
double time_sofar = (double) dl_total_time / 1000;
|
|
||||||
wgint bytes_remaining = bp->total_length - size;
|
wgint bytes_remaining = bp->total_length - size;
|
||||||
eta = (int) (time_sofar * bytes_remaining / bp->count + 0.5);
|
eta = (int) (dl_total_time * bytes_remaining / bp->count + 0.5);
|
||||||
bp->last_eta_value = eta;
|
bp->last_eta_value = eta;
|
||||||
bp->last_eta_time = dl_total_time;
|
bp->last_eta_time = dl_total_time;
|
||||||
}
|
}
|
||||||
@ -939,15 +942,15 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* When the download is done, print the elapsed time. */
|
/* When the download is done, print the elapsed time. */
|
||||||
double secs = dl_total_time / 1000;
|
|
||||||
/* Note to translators: this should not take up more room than
|
/* Note to translators: this should not take up more room than
|
||||||
available here. Abbreviate if necessary. */
|
available here. Abbreviate if necessary. */
|
||||||
strcpy (p, _(" in "));
|
strcpy (p, _(" in "));
|
||||||
move_to_end (p); /* not p+=6, think translations! */
|
move_to_end (p); /* not p+=6, think translations! */
|
||||||
if (secs >= 10)
|
if (dl_total_time >= 10)
|
||||||
strcpy (p, eta_to_human_short ((int) (secs + 0.5), false));
|
strcpy (p, eta_to_human_short ((int) (dl_total_time + 0.5), false));
|
||||||
else
|
else
|
||||||
sprintf (p, "%ss", print_decimal (secs));
|
sprintf (p, "%ss", print_decimal (dl_total_time));
|
||||||
move_to_end (p);
|
move_to_end (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
76
src/ptimer.c
76
src/ptimer.c
@ -39,16 +39,16 @@ so, delete this exception statement from your version. */
|
|||||||
ptimer_destroy -- destroy the timer.
|
ptimer_destroy -- destroy the timer.
|
||||||
ptimer_granularity -- returns the approximate granularity of the timers.
|
ptimer_granularity -- returns the approximate granularity of the timers.
|
||||||
|
|
||||||
Timers measure time in milliseconds, but the timings they return
|
Timers measure time in seconds, returning the timings as floating
|
||||||
are floating point numbers, so they can carry as much precision as
|
point numbers, so they can carry as much precision as the
|
||||||
the underlying system timer supports. For example, to measure the
|
underlying system timer supports. For example, to measure the time
|
||||||
time it takes to run a loop, you can use something like:
|
it takes to run a loop, you can use something like:
|
||||||
|
|
||||||
ptimer *tmr = ptimer_new ();
|
ptimer *tmr = ptimer_new ();
|
||||||
while (...)
|
while (...)
|
||||||
... loop ...
|
... loop ...
|
||||||
double msecs = ptimer_measure ();
|
double secs = ptimer_measure ();
|
||||||
printf ("The loop took %.2f ms\n", msecs); */
|
printf ("The loop took %.2fs\n", secs); */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ typedef struct timespec ptimer_system_time;
|
|||||||
CLOCK_MONOTONIC where available, CLOCK_REALTIME otherwise. */
|
CLOCK_MONOTONIC where available, CLOCK_REALTIME otherwise. */
|
||||||
static int posix_clock_id;
|
static int posix_clock_id;
|
||||||
|
|
||||||
/* Resolution of the clock, in milliseconds. */
|
/* Resolution of the clock, initialized in posix_init. */
|
||||||
static double posix_millisec_resolution;
|
static double posix_clock_resolution;
|
||||||
|
|
||||||
/* Decide which clock_id to use. */
|
/* Decide which clock_id to use. */
|
||||||
|
|
||||||
@ -148,11 +148,10 @@ posix_init (void)
|
|||||||
if (clock_getres (clocks[i].id, &r) < 0)
|
if (clock_getres (clocks[i].id, &r) < 0)
|
||||||
continue; /* clock_getres doesn't work for this clock */
|
continue; /* clock_getres doesn't work for this clock */
|
||||||
posix_clock_id = clocks[i].id;
|
posix_clock_id = clocks[i].id;
|
||||||
posix_millisec_resolution = r.tv_sec * 1000.0 + r.tv_nsec / 1000000.0;
|
posix_clock_resolution = (double) r.tv_sec + r.tv_nsec / 1e9;
|
||||||
/* Guard against broken clock_getres returning nonsensical
|
/* Guard against nonsense returned by a broken clock_getres. */
|
||||||
values. */
|
if (posix_clock_resolution == 0)
|
||||||
if (posix_millisec_resolution == 0)
|
posix_clock_resolution = 1e-3;
|
||||||
posix_millisec_resolution = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == countof (clocks))
|
if (i == countof (clocks))
|
||||||
@ -163,7 +162,7 @@ posix_init (void)
|
|||||||
strerror (errno));
|
strerror (errno));
|
||||||
/* Use CLOCK_REALTIME, but invent a plausible resolution. */
|
/* Use CLOCK_REALTIME, but invent a plausible resolution. */
|
||||||
posix_clock_id = CLOCK_REALTIME;
|
posix_clock_id = CLOCK_REALTIME;
|
||||||
posix_millisec_resolution = 1;
|
posix_clock_resolution = 1e-3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,14 +175,14 @@ posix_measure (ptimer_system_time *pst)
|
|||||||
static inline double
|
static inline double
|
||||||
posix_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
posix_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
||||||
{
|
{
|
||||||
return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
|
return ((pst1->tv_sec - pst2->tv_sec)
|
||||||
+ (pst1->tv_nsec - pst2->tv_nsec) / 1000000.0);
|
+ (pst1->tv_nsec - pst2->tv_nsec) / 1e9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
posix_resolution (void)
|
posix_resolution (void)
|
||||||
{
|
{
|
||||||
return posix_millisec_resolution;
|
return posix_clock_resolution;
|
||||||
}
|
}
|
||||||
#endif /* PTIMER_POSIX */
|
#endif /* PTIMER_POSIX */
|
||||||
|
|
||||||
@ -209,8 +208,8 @@ gettimeofday_measure (ptimer_system_time *pst)
|
|||||||
static inline double
|
static inline double
|
||||||
gettimeofday_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
gettimeofday_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
||||||
{
|
{
|
||||||
return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
|
return ((pst1->tv_sec - pst2->tv_sec)
|
||||||
+ (pst1->tv_usec - pst2->tv_usec) / 1000.0);
|
+ (pst1->tv_usec - pst2->tv_usec) / 1e6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
@ -246,9 +245,9 @@ typedef union {
|
|||||||
static bool windows_hires_timers;
|
static bool windows_hires_timers;
|
||||||
|
|
||||||
/* Frequency of high-resolution timers -- number of updates per
|
/* Frequency of high-resolution timers -- number of updates per
|
||||||
millisecond. Calculated the first time ptimer_new is called
|
second. Calculated the first time ptimer_new is called provided
|
||||||
provided that high-resolution timers are available. */
|
that high-resolution timers are available. */
|
||||||
static double windows_hires_msfreq;
|
static double windows_hires_freq;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
windows_init (void)
|
windows_init (void)
|
||||||
@ -259,7 +258,7 @@ windows_init (void)
|
|||||||
if (freq.QuadPart != 0)
|
if (freq.QuadPart != 0)
|
||||||
{
|
{
|
||||||
windows_hires_timers = true;
|
windows_hires_timers = true;
|
||||||
windows_hires_msfreq = (double) freq.QuadPart / 1000.0;
|
windows_hires_freq = (double) freq.QuadPart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +280,7 @@ static inline double
|
|||||||
windows_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
windows_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
|
||||||
{
|
{
|
||||||
if (windows_hires_timers)
|
if (windows_hires_timers)
|
||||||
return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_msfreq;
|
return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_freq;
|
||||||
else
|
else
|
||||||
return pst1->lores - pst2->lores;
|
return pst1->lores - pst2->lores;
|
||||||
}
|
}
|
||||||
@ -290,7 +289,7 @@ static double
|
|||||||
windows_resolution (void)
|
windows_resolution (void)
|
||||||
{
|
{
|
||||||
if (windows_hires_timers)
|
if (windows_hires_timers)
|
||||||
return 1.0 / windows_hires_msfreq;
|
return 1.0 / windows_hires_freq;
|
||||||
else
|
else
|
||||||
return 10; /* according to MSDN */
|
return 10; /* according to MSDN */
|
||||||
}
|
}
|
||||||
@ -303,8 +302,7 @@ struct ptimer {
|
|||||||
time, yields elapsed time. */
|
time, yields elapsed time. */
|
||||||
ptimer_system_time start;
|
ptimer_system_time start;
|
||||||
|
|
||||||
/* The most recent elapsed time, calculated by ptimer_measure().
|
/* The most recent elapsed time, calculated by ptimer_measure(). */
|
||||||
Measured in milliseconds. */
|
|
||||||
double elapsed_last;
|
double elapsed_last;
|
||||||
|
|
||||||
/* Approximately, the time elapsed between the true start of the
|
/* Approximately, the time elapsed between the true start of the
|
||||||
@ -341,8 +339,8 @@ ptimer_destroy (struct ptimer *pt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reset timer PT. This establishes the starting point from which
|
/* Reset timer PT. This establishes the starting point from which
|
||||||
ptimer_read() will return the number of elapsed milliseconds.
|
ptimer_measure() will return the elapsed time in seconds. It is
|
||||||
It is allowed to reset a previously used timer. */
|
allowed to reset a previously used timer. */
|
||||||
|
|
||||||
void
|
void
|
||||||
ptimer_reset (struct ptimer *pt)
|
ptimer_reset (struct ptimer *pt)
|
||||||
@ -353,13 +351,10 @@ ptimer_reset (struct ptimer *pt)
|
|||||||
pt->elapsed_pre_start = 0;
|
pt->elapsed_pre_start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Measure the elapsed time since timer creation/reset and return it
|
/* Measure the elapsed time since timer creation/reset. This causes
|
||||||
to the caller. The value remains stored for further reads by
|
the timer to internally call clock_gettime (or gettimeofday, etc.)
|
||||||
ptimer_read.
|
to update its idea of current time. The time is returned, but is
|
||||||
|
also stored for later access through ptimer_read().
|
||||||
This function causes the timer to call gettimeofday (or time(),
|
|
||||||
etc.) to update its idea of current time. To get the elapsed
|
|
||||||
interval in milliseconds, use ptimer_read.
|
|
||||||
|
|
||||||
This function handles clock skew, i.e. time that moves backwards is
|
This function handles clock skew, i.e. time that moves backwards is
|
||||||
ignored. */
|
ignored. */
|
||||||
@ -400,8 +395,9 @@ ptimer_measure (struct ptimer *pt)
|
|||||||
return elapsed;
|
return elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the elapsed time in milliseconds between the last call to
|
/* Return the most recent elapsed time measured with ptimer_measure.
|
||||||
ptimer_reset and the last call to ptimer_update. */
|
If ptimer_measure has not yet been called since the timer was
|
||||||
|
created or reset, this returns 0. */
|
||||||
|
|
||||||
double
|
double
|
||||||
ptimer_read (const struct ptimer *pt)
|
ptimer_read (const struct ptimer *pt)
|
||||||
@ -410,8 +406,8 @@ ptimer_read (const struct ptimer *pt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the assessed resolution of the timer implementation, in
|
/* Return the assessed resolution of the timer implementation, in
|
||||||
milliseconds. This is used by code that tries to substitute a
|
seconds. This is used by code that tries to substitute a better
|
||||||
better value for timers that have returned zero. */
|
value for timers that have returned zero. */
|
||||||
|
|
||||||
double
|
double
|
||||||
ptimer_resolution (void)
|
ptimer_resolution (void)
|
||||||
|
39
src/retr.c
39
src/retr.c
@ -55,7 +55,7 @@ so, delete this exception statement from your version. */
|
|||||||
/* Total size of downloaded files. Used to enforce quota. */
|
/* Total size of downloaded files. Used to enforce quota. */
|
||||||
SUM_SIZE_INT total_downloaded_bytes;
|
SUM_SIZE_INT total_downloaded_bytes;
|
||||||
|
|
||||||
/* Total download time in milliseconds. */
|
/* Total download time in seconds. */
|
||||||
double total_download_time;
|
double total_download_time;
|
||||||
|
|
||||||
/* If non-NULL, the stream to which output should be written. This
|
/* If non-NULL, the stream to which output should be written. This
|
||||||
@ -75,9 +75,7 @@ static struct {
|
|||||||
static void
|
static void
|
||||||
limit_bandwidth_reset (void)
|
limit_bandwidth_reset (void)
|
||||||
{
|
{
|
||||||
limit_data.chunk_bytes = 0;
|
xzero (limit_data);
|
||||||
limit_data.chunk_start = 0;
|
|
||||||
limit_data.sleep_adjust = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Limit the bandwidth by pausing the download for an amount of time.
|
/* Limit the bandwidth by pausing the download for an amount of time.
|
||||||
@ -95,25 +93,25 @@ limit_bandwidth (wgint bytes, struct ptimer *timer)
|
|||||||
/* Calculate the amount of time we expect downloading the chunk
|
/* Calculate the amount of time we expect downloading the chunk
|
||||||
should take. If in reality it took less time, sleep to
|
should take. If in reality it took less time, sleep to
|
||||||
compensate for the difference. */
|
compensate for the difference. */
|
||||||
expected = 1000.0 * limit_data.chunk_bytes / opt.limit_rate;
|
expected = (double) limit_data.chunk_bytes / opt.limit_rate;
|
||||||
|
|
||||||
if (expected > delta_t)
|
if (expected > delta_t)
|
||||||
{
|
{
|
||||||
double slp = expected - delta_t + limit_data.sleep_adjust;
|
double slp = expected - delta_t + limit_data.sleep_adjust;
|
||||||
double t0, t1;
|
double t0, t1;
|
||||||
if (slp < 200)
|
if (slp < 0.2)
|
||||||
{
|
{
|
||||||
DEBUGP (("deferring a %.2f ms sleep (%s/%.2f).\n",
|
DEBUGP (("deferring a %.2f ms sleep (%s/%.2f).\n",
|
||||||
slp, number_to_static_string (limit_data.chunk_bytes),
|
slp * 1000, number_to_static_string (limit_data.chunk_bytes),
|
||||||
delta_t));
|
delta_t));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DEBUGP (("\nsleeping %.2f ms for %s bytes, adjust %.2f ms\n",
|
DEBUGP (("\nsleeping %.2f ms for %s bytes, adjust %.2f ms\n",
|
||||||
slp, number_to_static_string (limit_data.chunk_bytes),
|
slp * 1000, number_to_static_string (limit_data.chunk_bytes),
|
||||||
limit_data.sleep_adjust));
|
limit_data.sleep_adjust));
|
||||||
|
|
||||||
t0 = ptimer_read (timer);
|
t0 = ptimer_read (timer);
|
||||||
xsleep (slp / 1000);
|
xsleep (slp);
|
||||||
t1 = ptimer_measure (timer);
|
t1 = ptimer_measure (timer);
|
||||||
|
|
||||||
/* Due to scheduling, we probably slept slightly longer (or
|
/* Due to scheduling, we probably slept slightly longer (or
|
||||||
@ -123,10 +121,10 @@ limit_bandwidth (wgint bytes, struct ptimer *timer)
|
|||||||
limit_data.sleep_adjust = slp - (t1 - t0);
|
limit_data.sleep_adjust = slp - (t1 - t0);
|
||||||
/* If sleep_adjust is very large, it's likely due to suspension
|
/* If sleep_adjust is very large, it's likely due to suspension
|
||||||
and not clock inaccuracy. Don't enforce those. */
|
and not clock inaccuracy. Don't enforce those. */
|
||||||
if (limit_data.sleep_adjust > 500)
|
if (limit_data.sleep_adjust > 0.5)
|
||||||
limit_data.sleep_adjust = 500;
|
limit_data.sleep_adjust = 0.5;
|
||||||
else if (limit_data.sleep_adjust < -500)
|
else if (limit_data.sleep_adjust < -0.5)
|
||||||
limit_data.sleep_adjust = -500;
|
limit_data.sleep_adjust = -0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
limit_data.chunk_bytes = 0;
|
limit_data.chunk_bytes = 0;
|
||||||
@ -185,7 +183,7 @@ write_data (FILE *out, const char *buf, int bufsize, wgint *skip,
|
|||||||
is incremented by the amount of data read from the network. If
|
is incremented by the amount of data read from the network. If
|
||||||
QTYWRITTEN is non-NULL, the value it points to is incremented by
|
QTYWRITTEN is non-NULL, the value it points to is incremented by
|
||||||
the amount of data written to disk. The time it took to download
|
the amount of data written to disk. The time it took to download
|
||||||
the data (in milliseconds) is stored to ELAPSED.
|
the data is stored to ELAPSED.
|
||||||
|
|
||||||
The function exits and returns the amount of data read. In case of
|
The function exits and returns the amount of data read. In case of
|
||||||
error while reading data, -1 is returned. In case of error while
|
error while reading data, -1 is returned. In case of error while
|
||||||
@ -267,7 +265,7 @@ fd_read_body (int fd, FILE *out, wgint toread, wgint startpos,
|
|||||||
if (opt.read_timeout)
|
if (opt.read_timeout)
|
||||||
{
|
{
|
||||||
double waittm;
|
double waittm;
|
||||||
waittm = (ptimer_read (timer) - last_successful_read_tm) / 1000;
|
waittm = ptimer_read (timer) - last_successful_read_tm;
|
||||||
if (waittm + tmout > opt.read_timeout)
|
if (waittm + tmout > opt.read_timeout)
|
||||||
{
|
{
|
||||||
/* Don't let total idle time exceed read timeout. */
|
/* Don't let total idle time exceed read timeout. */
|
||||||
@ -540,22 +538,23 @@ retr_rate (wgint bytes, double msecs)
|
|||||||
|
|
||||||
UNITS is zero for B/s, one for KB/s, two for MB/s, and three for
|
UNITS is zero for B/s, one for KB/s, two for MB/s, and three for
|
||||||
GB/s. */
|
GB/s. */
|
||||||
|
|
||||||
double
|
double
|
||||||
calc_rate (wgint bytes, double msecs, int *units)
|
calc_rate (wgint bytes, double secs, int *units)
|
||||||
{
|
{
|
||||||
double dlrate;
|
double dlrate;
|
||||||
|
|
||||||
assert (msecs >= 0);
|
assert (secs >= 0);
|
||||||
assert (bytes >= 0);
|
assert (bytes >= 0);
|
||||||
|
|
||||||
if (msecs == 0)
|
if (secs == 0)
|
||||||
/* If elapsed time is exactly zero, it means we're under the
|
/* If elapsed time is exactly zero, it means we're under the
|
||||||
resolution of the timer. This can easily happen on systems
|
resolution of the timer. This can easily happen on systems
|
||||||
that use time() for the timer. Since the interval lies between
|
that use time() for the timer. Since the interval lies between
|
||||||
0 and the timer's resolution, assume half the resolution. */
|
0 and the timer's resolution, assume half the resolution. */
|
||||||
msecs = ptimer_resolution () / 2.0;
|
secs = ptimer_resolution () / 2.0;
|
||||||
|
|
||||||
dlrate = 1000.0 * bytes / msecs;
|
dlrate = bytes / secs;
|
||||||
if (dlrate < 1024.0)
|
if (dlrate < 1024.0)
|
||||||
*units = 0;
|
*units = 0;
|
||||||
else if (dlrate < 1024.0 * 1024.0)
|
else if (dlrate < 1024.0 * 1024.0)
|
||||||
|
Loading…
Reference in New Issue
Block a user