home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: alt.sources
- From: hakanson@CSE.OGI.EDU (Marion Hakanson)
- Subject: [comp.protocols.time.ntp] Unix system clock resolution (precision)
- Message-ID: <1990Aug15.205349.12566@math.lsa.umich.edu>
- Date: Wed, 15 Aug 90 20:53:49 GMT
-
- Archive-name: clockres/15-Aug-90
- Original-posting-by: hakanson@CSE.OGI.EDU (Marion Hakanson)
- Original-subject: Unix system clock resolution (precision)
- Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
-
- [Reposted from comp.protocols.time.ntp.
- Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]
-
- Below find clockres.c, source to a program which will tell you (most of
- the time) the resolution of your gettimeofday(2) system call, and thus
- probably the precision of your system's underlying clock. It has uses
- other than satisfying curiosity: you may be able to use it to tell
- an ntp server what precision to use, or to find out how accurate various
- performance measurements might be. Do keep in mind that ntpd's estimate
- using the kernel HZ value is probably best for most machines.
-
- Bug reports would be welcome to me, though it's pretty simple. I
- don't really care to create an archive of the results on various and
- sundry computer systems -- it takes less time to compile and run the
- program than it does to ftp a list from somewhere to look up your
- machine. But perhaps such an archive would be of use to prospective
- purchasers of hardware. I certainly ran into some surprises (like
- maybe 2^-6 isn't "bad" enough for an NTP precision). Here's a list of
- what I've encountered so far, in no particular order (the "or better"
- is explained in the program header commentary).
-
- =============
- Hardware O/S software Resolution (microseconds)
-
- HP-9000/320 4.3bsd/Univ.Utah 336 or better (prob. 4)
- HP-9000/200 4.3bsd/Berkeley 830 or better (prob. 4)
-
- DEC-DS2100 Ultrix-3.1 (UWS-2.2) 3906
- DEC-uVAX/II 4.3bsd/MtXinu 10000
-
- Sun-4/60 SunOS-4.0.3c 53 or better (maybe 1?)
- Sun-4/60 SunOS-4.1(c) 62 or better (maybe 1?)
- Sun-4/65 SunOS-4.1(c) 10000
- Sun-4/110 SunOS-4.0.3 10000
- Sun-4/280 SunOS-4.0.3 10000
- Sun-3/50 SunOS-4.0.3 20000
- Sun-3/60 SunOS-4.1 20000
-
- Sequent-S81 DYNIX-3.0.12 10000
- Sequent-B21 DYNIX-3.1.alpha1 10000
-
- Tek-431[57] UTek-3.1 50000 (missed the boat again)
- =============
-
-
- =============
- #ifndef lint
- char rcsid[] = "$Id: clockres.c,v 1.9 90/08/14 23:41:21 hakanson Exp $";
- #endif /* lint */
-
- /*
- * Determine the resolution of the system clock (gettimeofday(2)).
- * Marion Hakanson (hakanson@cse.ogi.edu)
- * Oregon Graduate Institute of Science and Technology
- *
- * The idea is to call gettimeofday(2), then repeatedly call it again
- * until you get a different value. The difference between the two
- * values should be the resolution (precision) of the system clock.
- * A little noise sometimes creeps in, due to adjtime(2)'s being done,
- * but in practice this appears rarely and can be factored out by running
- * this test program repeatedly (say 10 times). There is a "-v" option
- * to print out the two differing timestamps (and the number of calls
- * it took before a difference was detected). You may occasionally
- * see two (but never more) of these printed out before a result is
- * announced -- this is to avoid anomalies with comparing microseconds
- * when a wrap to the next full second has occurred.
- *
- * The big flaw to this approach is that most 4.3bsd-based systems have
- * in their kernels a microtime() routine which is supposed to return
- * the current time to the microsecond. A "good" implementation would
- * (e.g.) read a hardware interval timer to determine how many usec's
- * had passed since the last clock tick. But much hardware seems to
- * lack such a timer, and as a result, most implementations of microtime()
- * fake it by adding a microsecond to the current time for each subsequent
- * call to microtime() -- just to ensure that two invocations never return
- * exactly the same value (the fake microseconds go away at the next clock
- * tick) . Since most machines (known to mortals) these days cannot make
- * a system call in one microsecond, this program has a hack in it to
- * detect these "fake" microtime() implementations by adding the number
- * of gettimeofday(2) calls to the initial timestamp before comparing
- * with the most recent timestamp. A ">=" test is used to work with
- * older bsd's (like 4.2), where two subsequent timestamps often are
- * the same (within the value of a tick), and the "-f" option disables
- * the "fake" microtime() workaround. More irregular "fakes" will no
- * doubt be reported as terrific (but erroneous) clock resolutions.
- *
- * A small flaw is that if a machine has a clock resolution finer than
- * the time it takes to make a single pass through the loop, then the
- * program reports that value as the resolution of the clock, rather
- * than the actual resolution. A warning about this is printed when
- * a real difference is detected after only one pass (it says "... XX
- * microseconds or better" instead of just "... XX microseconds").
- * Again, repeated runs can show this condition if the value seems to
- * fluctuate by a few microseconds and/or vary with system load (a
- * "genuine" result seems to stay rock solid across invocations).
- * In practice, few real machines seem to encounter this behavior,
- * and you should count yourself lucky if you have one.
- */
-
- #include <stdio.h>
- #include <sys/time.h>
-
- extern int getopt();
-
- main(argc, argv)
- int argc; char *argv[];
- {
- int verbose;
- register int fakemicro;
- int again;
- struct timeval t1, t2;
- register int calls;
- int c;
-
-
- verbose = 0;
- fakemicro = 1;
-
- while ( (c = getopt(argc, argv, "fv")) != EOF ) {
- switch ( c ) {
- case 'f':
- fakemicro = 0;
- break;
- case 'v':
- verbose = 1;
- break;
- case '?':
- fprintf(stderr, "usage: %s [-fv]\n", argv[0]);
- exit(1);
- }
- }
-
-
- again = 0;
-
- top:
-
- if (again > 1) {
- fprintf (stderr, "%s: More than one second passed, giving up.\n", argv[0]);
- exit(1);
- }
-
- again++;
-
- calls = 0;
-
- (void) gettimeofday(&t1, NULL);
-
- do {
- calls++;
- (void) gettimeofday(&t2, NULL);
- } while ( (t1.tv_sec == t2.tv_sec)
- && ( fakemicro ? ((t1.tv_usec+calls) >= t2.tv_usec)
- : (t1.tv_usec == t2.tv_usec) ) );
-
- if (verbose) {
- printf ("t1 %d.%06.6d t2 %d.%06.6d calls %d\n",
- t1.tv_sec, t1.tv_usec, t2.tv_sec, t2.tv_usec, calls);
- }
-
- /* Check for wrap to next second */
- if (t1.tv_sec != t2.tv_sec)
- goto top;
-
- printf ("Clock step resolution %d microseconds", t2.tv_usec - t1.tv_usec);
-
- if ( calls == 1 )
- printf (" or better");
-
- printf("\n");
-
- exit(0);
- }
- =============
-
- --
- Marion Hakanson Domain: hakanson@cse.ogi.edu
- UUCP : {hp-pcd,tektronix}!ogicse!hakanson
-