[chrony-users] Measuring clock offset results

[ Thread Index | Date Index | More chrony.tuxfamily.org/chrony-users Archives ]


Hi all,

Thank you for suggesting we use /sys/class/pps/pps1/assert to measure the clock. (Source code below.) Here's a comparison of the results between chrony and ntpd over 24 hours:

https://ibb.co/album/5YxH2m

Chrony clearly improves the offsets to sub-20 microseconds much of the time. We're seeing some spikes in the timing, though, that exceed ntpd.* The chrony configuration file is the same as in the other thread (https://www.mail-archive.com/chrony-users@xxxxxxxxxxxxxxxxxxxx/msg03281.html).

Other processes may be affected by changing the CPU, so we haven't switched to a constant frequency nor disabled the power saving states (e.g. idle=poll).

Setting sched_priority to 1 yields a modest improvement over an hour:

https://ibb.co/album/1Z824p

Are there any other ways we could help chronyd stay below 20 microseconds (e.g., optimized build) that may have been overlooked (besides using GPIO)?

Many thanks!

*ntpd had one 1500+ us outlier, which we removed from the graphs.

P.S.
Code improvement suggestions welcome:

// SOF
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

#define PPS_DEVICE "/sys/class/pps/pps1/assert"

static void diff_timespec(
  const struct timespec *time1,
  const struct timespec *time0,
  struct timespec* diff ) {
  diff->tv_sec = time1->tv_sec - time0->tv_sec;
  diff->tv_nsec = time1->tv_nsec - time0->tv_nsec;

  if( diff->tv_nsec < 0 ) {
    // nsec/sec
    diff->tv_nsec += 1000000000;
    diff->tv_sec--;
  }
}

int main( int argc, char** argv ) {
  struct timespec curr_pps_time = {0};
  struct timespec prev_pps_time = {0};
  int curr_assert = 0;
  int prev_assert = -1;
  struct timespec diff = {0};
  struct timespec drift = {0};
  char pps_buff[64] = {'\0'};

  printf( "seconds,nanoSeconds\n" );

  FILE* pps_fd = fopen( PPS_DEVICE, "r" );

  while( 1 ) {
    fread( pps_buff,1, 63, pps_fd );

    sscanf( pps_buff, "%ld.%ld#%d",
      &curr_pps_time.tv_sec,
      &curr_pps_time.tv_nsec,
      &curr_assert );

    if( prev_assert == -1 ) {
      prev_assert = curr_assert;
      prev_pps_time.tv_sec = curr_pps_time.tv_sec;
      prev_pps_time.tv_nsec = curr_pps_time.tv_nsec;
    }
   
    if( ( curr_assert - prev_assert ) == 1 ) {
      struct timespec _one_second_ = {.tv_sec = 1, .tv_nsec = 0};

      diff_timespec( &curr_pps_time, &prev_pps_time, &diff );
      diff.tv_sec >= 1
        ? diff_timespec( &diff, &one_second, &drift )
        : diff_timespec( &one_second, &diff, &drift );

      printf( "%ld,%ld\n", drift.tv_sec, drift.tv_nsec );
      fflush( stdout );

      prev_assert = curr_assert;
      prev_pps_time.tv_sec = curr_pps_time.tv_sec;
      prev_pps_time.tv_nsec = curr_pps_time.tv_nsec;
    }

    fseek( pps_fd,0,SEEK_SET );
    usleep( 250000 );
  }

  fclose( pps_fd );
  return 0;
}
// EOF

Graphs were generated using R:

# SOF

plotOffsets <- function( filename ) {

  csv.data <- read.table( filename, sep=",", header=T, na.strings="", stringsAsFactors=F );

 

  csv.data$nanoSeconds <- csv.data$nanoSeconds / 1000;

 

  plot(x=1:length(csv.data$nanoSeconds), csv.data$nanoSeconds, xlab="index", ylab="offset (us)", type="l");

}

# EOF




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/