NTP Serial Port Jitter

NTP reference clocks that output their time tick as part of an ASCII data stream suffer from the effects of jitter in the operating system serial port driver. This page shows the effect of serial port tuning.

I talk about Linux first, and then provide some FreeBSD information further down the page.

Linux

The short answer is that under Linux, using the setserial command to set the "low_latency" flag is the right thing to do: setserial /dev/ttyS0 low_latency".

I used an HP Z3801A GPS-disciplined oscillator (a telecomm packaged unit very similar to the HP 58503A "SmartClock") hooked to a PC running Linux kernel 2.4.21 with the "PPSkit" patches applied, and NTP version 4.2.0. The PC is an Athlon 2200+ and the serial ports are on the motherboard.

I tested four configurations for about one day at a time, using the offset and jitter data from NTP's "peerstats" log file as the data. The table and graphs below show the performance for each configuration.

Note: These results measure jitter in the serial data stream only. If you are using a "PPS" interface that utilizes a pulse on the DCD or other control signal of a serial port, that doesn't seem to be impacted by any of these settings. Here are some statistics for the PPS offset and stability showing their immunity to the configuration tests done here.

I collected data with the "low_latency" flag both set and unset ("^low_latency").

Because the FIFO buffer in modern UART chips can contribute to jitter, I attempted to disable the FIFO by forcing the kernel to think that the chip was an old 8250 rather than the more modern 16550A. As shown in the results, this didn't make any difference. It's possible that my UART-forcing trick didn't really disable the FIFO, but I have been unable to find any information on how to do so in any other way.

Here are some basic statistics from the ~24 hour run in each configuration. All values are in milliseconds, and the "Range" value is the absolute difference between the minimum and maximum values recorded.

  Mean
Offset
Offset
Range
Offset
StdDev
Mean
Jitter
Jitter
Range
Jitter
StdDev
^low+16550a -4.711616.5382.9735 4.335212.9241.1380
^low+8250 -4.755916.1333.0265 4.389714.3991.2271
low+8250 0.241297.59900.70391 0.544087.58620.82720
low+16550a 0.232987.91200.71086 0.571787.70060.81877

You can see two things from this data beyond the obvious facts that the low latency flag makes a big difference, while the UART setting doesn't.

First, there is much greater average offset -- about -4.7ms compared with +0.24ms -- when the low_latency flag is not set. That makes sense, considering that the "setserial" documentation indicates that the serial subsystem normally has a 5-10ms delay.

Second, and this is shown much more clearly by the charts below, when the low latency flag is set, the readings cluster very closely to an offset "ceiling" that is never exceeded; the noise is all in individual readings that have significantly increased delay. When the flag is not set, the mean is much closer to the median value and the data looks much more like a triangle waveform.

Speaking of graphs, here they are:

Linux PPS Performance

Serial port configuration doesn't have any significant impact on the performance of the PPS signal (note -- these values are in microseconds, not the milliseconds used for the ASCII stream statistics):

  Mean
Offset
Offset
Range
Offset
StdDev
Mean
Jitter
Jitter
Range
Jitter
StdDev
^low+16550a 6.075221.9352.1903 1.43149.17400.93767
^low+8250 6.610515.8862.7639 1.92769.62901.3486
low_latency+8250 6.347915.8832.3783 1.37977.98400.70352
low+16550a 6.545516.6732.3301 1.42527.63900.80232

FreeBSD

FreeBSD doesn't have a "low latency" option, but it does have flags that disable the UART FIFO. These are statistics, followed by a graph or two, of the performance of a FreeBSD 4.9 system with the sio flags set to 0x02 to disable the UART FIFO. This information is based on a single run of about 9 days worth of data.

In addition to a Z3801A GPS clock, the FreeBSD machine also has attached a Spectracom 8170 WWVB clock. I've included its performance here as well; it seems to have a much better serial data stream performance than the Z3801A, though its PPS output is not nearly as good.

As with Linux, the PPS performance doesn't seem to depend on the FIFO settings.

  Mean
Offset
Offset
Range
Offset
StdDev
Mean
Jitter
Jitter
Range
Jitter
StdDev
Z3801A ASCII 1.2960ms13.212ms2.9132ms 4.0191ms10.959ms1.0817ms
Z3801A PPS 2.1986us35.819us3.3565us 7.6544us23.702us0.26831us
Spectracom 808.73ms2.4297ms0.22846ms 0.019211ms0.94983ms0.024000ms