[svn] New timer functions. Published in <sxs8zkp28vk.fsf@florida.arsdigita.de>.

This commit is contained in:
hniksic 2001-04-24 16:09:45 -07:00
parent 5674776cad
commit 45eea7387f
7 changed files with 217 additions and 78 deletions

View File

@ -1,3 +1,26 @@
2001-04-25 Hrvoje Niksic <hniksic@arsdigita.com>
* utils.c: Document timer functions.
* retr.c (rate): Use it.
(rate): Print in GB/s if transfer rate exceeds 1 GB/s.
* utils.c (wtimer_granularity): New function.
2001-04-24 Hrvoje Niksic <hniksic@arsdigita.com>
* retr.c (show_progress): Ditto.
* ftp.c (getftp): Ditto.
* http.c (gethttp): Use new timer functions.
* utils.c (wtimer_allocate): New function.
(wtimer_new): Ditto.
(wtimer_delete): Ditto.
(wtimer_reset): Ditto.
(wtimer_elapsed): Ditto.
2001-04-24 Hrvoje Niksic <hniksic@arsdigita.com>
* utils.c (long_to_string): New, faster version. Favors smaller

View File

@ -114,6 +114,7 @@ getftp (struct urlinfo *u, long *len, long restval, ccon *con)
FILE *fp;
char *user, *passwd, *respline;
char *tms, *tmrate;
struct wget_timer *timer;
unsigned char pasv_addr[6];
int cmd = con->cmd;
int passive_mode_open = 0;
@ -870,10 +871,11 @@ Error in server response, closing control connection.\n"));
legible (expected_bytes - restval));
logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
}
reset_timer ();
timer = wtimer_new ();
/* Get the contents of the document. */
res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
con->dltime = elapsed_time ();
con->dltime = wtimer_elapsed (timer);
wtimer_delete (timer);
tms = time_str (NULL);
tmrate = rate (*len - restval, con->dltime, 0);
/* Close data connection socket. */

View File

@ -526,6 +526,7 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt)
static SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
#endif /* HAVE_SSL */
struct wget_timer *timer;
char *cookies = NULL;
/* Whether this connection will be kept alive after the HTTP request
@ -1333,12 +1334,13 @@ Accept: %s\r\n\
should be some overhead information. */
if (opt.save_headers)
fwrite (all_headers, 1, all_length, fp);
reset_timer ();
timer = wtimer_new ();
/* Get the contents of the document. */
hs->res = get_contents (sock, fp, &hs->len, hs->restval,
(contlen != -1 ? contlen : 0),
&rbuf, keep_alive);
hs->dltime = elapsed_time ();
hs->dltime = wtimer_elapsed (timer);
wtimer_delete (timer);
{
/* Close or flush the file. We have to be careful to check for
error here. Checking the result of fwrite() is not enough --

View File

@ -47,13 +47,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
extern int errno;
#endif
#ifdef WINDOWS
LARGE_INTEGER internal_time;
#else
/* Internal variables used by the timer. */
static long internal_secs, internal_msecs;
#endif
/* See the comment in gethttp() why this is needed. */
int global_download_count;
@ -175,10 +168,11 @@ print_percentage (long bytes, long expected)
static int
show_progress (long res, long expected, enum spflags flags)
{
static struct wget_timer *timer;
static long line_bytes;
static long offs, initial_skip;
static int ndot, nrow;
static long last_timer, time_offset;
static long last_timer_value, time_offset;
int any_output = 0;
if (flags == SP_FINISH)
@ -186,7 +180,7 @@ show_progress (long res, long expected, enum spflags flags)
int dot = ndot;
char *tmpstr = (char *)alloca (2 * opt.dots_in_line + 1);
char *tmpp = tmpstr;
time_offset = elapsed_time () - last_timer;
time_offset = wtimer_elapsed (timer) - last_timer_value;
for (; dot < opt.dots_in_line; dot++)
{
if (!(dot % opt.dot_spacing))
@ -217,7 +211,10 @@ show_progress (long res, long expected, enum spflags flags)
offs = 0L;
ndot = nrow = 0;
line_bytes = (long)opt.dots_in_line * opt.dot_bytes;
last_timer = elapsed_time ();
if (!timer)
timer = wtimer_allocate ();
wtimer_reset (timer);
last_timer_value = 0;
time_offset = 0;
initial_skip = res;
if (res)
@ -247,8 +244,8 @@ show_progress (long res, long expected, enum spflags flags)
++ndot;
if (ndot == opt.dots_in_line)
{
time_offset = elapsed_time () - last_timer;
last_timer += time_offset;
time_offset = wtimer_elapsed (timer) - last_timer_value;
last_timer_value += time_offset;
ndot = 0;
++nrow;
@ -264,66 +261,11 @@ show_progress (long res, long expected, enum spflags flags)
/* Reenable flushing. */
opt.no_flush = 0;
if (any_output)
/* Force flush. #### Oh, what a kludge! */
/* Force flush. */
logflush ();
return any_output;
}
/* Reset the internal timer. */
void
reset_timer (void)
{
#ifndef WINDOWS
/* Under Unix, the preferred way to measure the passage of time is
through gettimeofday() because of its granularity. However, on
some old or weird systems, gettimeofday() might not be available.
There we use the simple time(). */
# ifdef HAVE_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
internal_secs = t.tv_sec;
internal_msecs = t.tv_usec / 1000;
# else /* not HAVE_GETTIMEOFDAY */
internal_secs = time (NULL);
internal_msecs = 0;
# endif /* not HAVE_GETTIMEOFDAY */
#else /* WINDOWS */
/* Under Windows, use Windows-specific APIs. */
FILETIME ft;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);
internal_time.HighPart = ft.dwHighDateTime;
internal_time.LowPart = ft.dwLowDateTime;
#endif /* WINDOWS */
}
/* Return the time elapsed from the last call to reset_timer(), in
milliseconds. */
long
elapsed_time (void)
{
#ifndef WINDOWS
# ifdef HAVE_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
return ((t.tv_sec - internal_secs) * 1000
+ (t.tv_usec / 1000 - internal_msecs));
# else /* not HAVE_GETTIMEOFDAY */
return 1000 * ((long)time (NULL) - internal_secs);
# endif /* not HAVE_GETTIMEOFDAY */
#else /* WINDOWS */
FILETIME ft;
SYSTEMTIME st;
LARGE_INTEGER li;
GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);
li.HighPart = ft.dwHighDateTime;
li.LowPart = ft.dwLowDateTime;
return (long) ((li.QuadPart - internal_time.QuadPart) / 1e4);
#endif /* WINDOWS */
}
/* Print out the appropriate download rate. Appropriate means that if
rate is > 1024 bytes per second, kilobytes are used, and if rate >
1024 * 1024 bps, megabytes are used.
@ -336,15 +278,25 @@ rate (long bytes, long msecs, int pad)
static char res[15];
double dlrate;
if (!msecs)
++msecs;
if (msecs == 0)
/* If elapsed time is 0, it means we're under the granularity of
the timer. This often happens on systems that use time() for
the timer. */
msecs = wtimer_granularity ();
dlrate = (double)1000 * bytes / msecs;
if (dlrate < 1024.0)
sprintf (res, pad ? "%7.2f B/s" : "%.2f B/s", dlrate);
else if (dlrate < 1024.0 * 1024.0)
sprintf (res, pad ? "%7.2f KB/s" : "%.2f KB/s", dlrate / 1024.0);
else
else if (dlrate < 1024.0 * 1024.0 * 1024.0)
sprintf (res, pad ? "%7.2f MB/s" : "%.2f MB/s", dlrate / (1024.0 * 1024.0));
else
/* Maybe someone will need this one day. More realistically, it
will get tickled by buggy timers. */
sprintf (res, pad ? "%7.2f GB/s" : "%.2f GB/s",
dlrate / (1024.0 * 1024.0 * 1024.0));
return res;
}

View File

@ -28,10 +28,7 @@ uerr_t retrieve_url PARAMS ((const char *, char **, char **,
const char *, int *));
uerr_t retrieve_from_file PARAMS ((const char *, int, int *));
void reset_timer PARAMS ((void));
long elapsed_time PARAMS ((void));
char *rate PARAMS ((long, long, int));
void printwhat PARAMS ((int, int));
void downloaded_increase PARAMS ((unsigned long));

View File

@ -1532,6 +1532,160 @@ long_to_string (char *buffer, long number)
#undef DIGITS_18
#undef DIGITS_19
/* Support for timers. */
#undef TIMER_WINDOWS
#undef TIMER_GETTIMEOFDAY
#undef TIMER_TIME
/* Depending on the OS and availability of gettimeofday(), one and
only one of the above constants will be defined. Virtually all
modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
use TIMER_WINDOWS. TIMER_TIME is a catch-all method for
non-Windows systems without gettimeofday.
#### Perhaps we should also support ftime(), which exists on old
BSD 4.2-influenced systems? (It also existed under MS DOS Borland
C, if memory serves me.) */
#ifdef WINDOWS
# define TIMER_WINDOWS
#else /* not WINDOWS */
# ifdef HAVE_GETTIMEOFDAY
# define TIMER_GETTIMEOFDAY
# else
# define TIMER_TIME
# endif
#endif /* not WINDOWS */
struct wget_timer {
#ifdef TIMER_GETTIMEOFDAY
long secs;
long usecs;
#endif
#ifdef TIMER_TIME
time_t secs;
#endif
#ifdef TIMER_WINDOWS
ULARGE_INTEGER wintime;
#endif
};
/* Allocate a timer. It is not legal to do anything with a freshly
allocated timer, except call wtimer_reset(). */
struct wget_timer *
wtimer_allocate (void)
{
struct wget_timer *wt =
(struct wget_timer *)xmalloc (sizeof (struct wget_timer));
return wt;
}
/* Allocate a new timer and reset it. Return the new timer. */
struct wget_timer *
wtimer_new (void)
{
struct wget_timer *wt = wtimer_allocate ();
wtimer_reset (wt);
return wt;
}
/* Free the resources associated with the timer. Its further use is
prohibited. */
void
wtimer_delete (struct wget_timer *wt)
{
xfree (wt);
}
/* Reset timer WT. This establishes the starting point from which
wtimer_elapsed() will return the number of elapsed
milliseconds. It is allowed to reset a previously used timer. */
void
wtimer_reset (struct wget_timer *wt)
{
#ifdef TIMER_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
wt->secs = t.tv_sec;
wt->usecs = t.tv_usec;
#endif
#ifdef TIMER_TIME
wt->secs = time (NULL);
#endif
#ifdef TIMER_WINDOWS
FILETIME ft;
SYSTEMTIME st;
GetSystemTime (&st);
SystemTimeToFileTime (&st, &ft);
wt->wintime.HighPart = ft.dwHighDateTime;
wt->wintime.LowPart = ft.dwLowDateTime;
#endif
}
/* Return the number of milliseconds elapsed since the timer was last
reset. It is allowed to call this function more than once to get
increasingly higher elapsed values. */
long
wtimer_elapsed (struct wget_timer *wt)
{
#ifdef TIMER_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
return (t.tv_sec - wt->secs) * 1000 + (t.tv_usec - wt->usecs) / 1000;
#endif
#ifdef TIMER_TIME
time_t now = time (NULL);
return 1000 * (now - wt->secs);
#endif
#ifdef WINDOWS
FILETIME ft;
SYSTEMTIME st;
ULARGE_INTEGER uli;
GetSystemTime (&st);
SystemTimeToFileTime (&st, &ft);
uli.HighPart = ft.dwHighDateTime;
uli.LowPart = ft.dwLowDateTime;
return (long)((uli.QuadPart - wt->wintime.QuadPart) / 10000);
#endif
}
/* Return the assessed granularity of the timer implementation. This
is important for certain code that tries to deal with "zero" time
intervals. */
long
wtimer_granularity (void)
{
#ifdef TIMER_GETTIMEOFDAY
/* Granularity of gettimeofday is hugely architecture-dependent.
However, it appears that on modern machines it is better than
1ms. */
return 1;
#endif
#ifdef TIMER_TIME
/* This is clear. */
return 1000;
#endif
#ifdef TIMER_WINDOWS
/* ? */
return 1;
#endif
}
/* This should probably be at a better place, but it doesn't really
fit into html-parse.c. */

View File

@ -39,6 +39,8 @@ struct file_memory {
int mmap_p;
};
struct wget_timer;
char *time_str PARAMS ((time_t *));
char *datetime_str PARAMS ((time_t *));
@ -88,6 +90,13 @@ char *legible_very_long PARAMS ((VERY_LONG_TYPE));
int numdigit PARAMS ((long));
void long_to_string PARAMS ((char *, long));
struct wget_timer *wtimer_allocate PARAMS ((void));
struct wget_timer *wtimer_new PARAMS ((void));
void wtimer_delete PARAMS ((struct wget_timer *));
void wtimer_reset PARAMS ((struct wget_timer *));
long wtimer_elapsed PARAMS ((struct wget_timer *));
long wtimer_granularity PARAMS ((void));
char *html_quote_string PARAMS ((const char *));
#endif /* UTILS_H */