From 45eea7387f05fa8c2d55694663d77f4a5a3dec3b Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 24 Apr 2001 16:09:45 -0700 Subject: [PATCH] [svn] New timer functions. Published in . --- src/ChangeLog | 23 ++++++++ src/ftp.c | 6 +- src/http.c | 6 +- src/retr.c | 94 ++++++++---------------------- src/retr.h | 3 - src/utils.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 9 +++ 7 files changed, 217 insertions(+), 78 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 78c48bb7..313b504d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,26 @@ +2001-04-25 Hrvoje Niksic + + * 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 + + * 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 * utils.c (long_to_string): New, faster version. Favors smaller diff --git a/src/ftp.c b/src/ftp.c index 9a0f9a3f..1e8ad517 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -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. */ diff --git a/src/http.c b/src/http.c index 7b9578d1..22fabdc6 100644 --- a/src/http.c +++ b/src/http.c @@ -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 -- diff --git a/src/retr.c b/src/retr.c index 1667f52e..dd6380d3 100644 --- a/src/retr.c +++ b/src/retr.c @@ -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; } diff --git a/src/retr.h b/src/retr.h index c69c493e..4455e7bd 100644 --- a/src/retr.h +++ b/src/retr.h @@ -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)); diff --git a/src/utils.c b/src/utils.c index 7163ea71..a8e30b9f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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. */ diff --git a/src/utils.h b/src/utils.h index 2624322f..edc779f7 100644 --- a/src/utils.h +++ b/src/utils.h @@ -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 */ -- 2.39.2