29 September 2006

Fine-tune your system clock

These days it's really pretty easy to just run ntpd and have your system clock almost perfectly accurate all the time. But, you may prefer not to run ntpd. You may have security concerns with it or resource concerns or network problems. Or, maybe you're just running a work station and you don't want to waste a time server's resources. Here is an interesting little trick to take the major drift out of your system clock.

First, we still need ntpd or ntpdate to get a baseline of how much our system clock is drifting. I usually use ntpdate to get this baseline. (For that matter, I usually continue to use ntpdate after tuning because you just cannot remove all of the drift.) After running ntpdate once a day for a few days and directing all the output to a log file (with a cron job like this perhaps: "25 3 * * * /usr/sbin/ntpdate >> /var/log/ntp 2>&1"), I would check the log file and see something like this:

5 Jun 03:24:56 ntpdate[4971]: step time server offset -4.676964 sec
6 Jun 03:24:56 ntpdate[7630]: step time server offset -4.677364 sec
8 Jun 03:25:02 ntpdate[1135]: step time server offset 1.038868 sec
9 Jun 03:24:57 ntpdate[3474]: step time server offset -4.688533 sec
10 Jun 03:24:56 ntpdate[5884]: step time server offset -4.694951 sec
11 Jun 03:24:56 ntpdate[8205]: step time server offset -4.710710 sec
12 Jun 03:24:57 ntpdate[10432]: step time server offset -4.712613 sec
13 Jun 03:24:56 ntpdate[12957]: step time server offset -4.685443 sec

This is a real example, though old. And, it seems someone rebooted the machine once to play some game. So, I'm definitely throwing out the 8 June number. I'll average the remaining 7 figures and get -4.692368. Next, you need to find out what timer your machine is using and what its default frequency is. That's pretty easy. You can either look in "/var/run/dmesg.boot" or type "sysctl machdep". The two alternatives I've seen are the "i8254" (on older machines) and the acpi_timer. Many machines have both, in which case it is probably actually using the acpi_timer for its system clock -- and that's the case in this example. The default frequency for the acpi_timer is 3579545 and that has been giving us about 86404.7 seconds in a day, when there are really 86400. The adjustment we need to make to our clock might be counter-intuitive -- to slow it down you must raise the timer's frequency. (And, vice-versa.) To find your new, improved frequency you can use this formula:

(86400 - 4.692368)

And, then our new frequency ends up being 3579739.41, which must be rounded to an integer. You can apply this frequency by changing the sysctl variable. As root, I entered the command "sysctl machdep.acpi_timer_freq=3579739" ... and my clock hasn't been the same since then. Take a look:

21 Jun 03:25:01 ntpdate[8299]: adjust time server offset -0.009996 sec
22 Jun 03:25:01 ntpdate[10609]: adjust time server offset -0.001996 sec
23 Jun 03:25:01 ntpdate[12909]: adjust time server offset 0.007902 sec

Also, to make this change persistent across reboots you should edit the file "/etc/sysctl.conf" and place a line in it like this "machdep.acpi_timer_freq=3579739" (but with the frequency you found for your machine :) ). That's pretty much it!

The formula I used above to find the new frequency is the result of experimentation. Instead of adding the average offset to the denominator on the right hand side, you could also subtract it from the numerator and get pretty much the same result. (Only because the offsets are so small compared to 86400.) Also, if you're going to do this, please continue to run ntpdate and verify that you got it right! I did get it backwards once and doubled my clock's drift for a day. (Whoops.)

(Postscript. You can use ntpd fine after you've tuned your clock this way. In fact, I'm sure there must be a way to adjust your timer frequency based on an ntpd calculated drift, but I haven't tried to find it. IP's have been changed to protect the innocent -- I don't actually use for ntp services. You should try to find a public server close to you. I used the "HTML Equation Preprocessor" at http://www.miracosta.edu/home/sschaefer/eqsyntax.html to get the HTML table code for the equation above.)

[ tags: , , , ]



Post a Comment

<< Home