123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- /*
- * clock_test. A simple program to test the latency of the clock_gettime() call
- *
- * Compile: gcc clock_test.c -lm -o clock_test
- *
- * Written by: Gary E. Miller <gem@rellim.com>
- * This file is Copyright 2018 by the GPSD project
- * SPDX-License-Identifier: BSD-2-clause
- */
- #include <getopt.h> /* for getopt() */
- #include <limits.h> /* for LONG_MAX */
- #include <math.h> /* for pow(), sqrt() */
- #include <stdio.h> /* for printf() */
- #include <stdlib.h> /* for qsort() */
- #include <time.h> /* for time_t */
- #define NUM_TESTS 101 /* default samples, make it odd for a clean median */
- #define DELAY 10000000 /* default delay between samples in ns, 10 ms is good */
- int compare_long( const void *ap, const void *bp)
- {
- long a = *((long *)ap);
- long b = *((long *)bp);
- if ( a < b ) return -1;
- if ( a > b ) return 1;
- return 0;
- }
- int main(int argc, char **argv)
- {
- int i;
- int opt; /* for getopts() */
- int verbose = 0;
- int samples = NUM_TESTS;
- long delay = DELAY;
- long *diffs = NULL;
- long min = LONG_MAX, max = 0, sum = 0, mean = 0, median = 0;
- double stddev = 0.0;
-
- while ((opt = getopt(argc, argv, "d:hvn:")) != -1) {
- switch (opt) {
- case 'd':
- delay = atol(optarg);
- break;
- case 'n':
- samples = atoi(optarg);
- /* make odd, for a good median */
- if ( (samples & 1) == 0) {
- samples += 1;
- }
- break;
- case 'v':
- verbose = 1;
- break;
- case 'h':
- /* fall through */
- default: /* '?' */
- fprintf(stderr, "Usage: %s [-h] [-d nsec] [-n samples] [-v]\n\n", argv[0]);
- fprintf(stderr, "-d nsec : nano seconde paus between samples\n");
- fprintf(stderr, "-h : help\n");
- fprintf(stderr, "-n samples : Number of samples, default %d\n", NUM_TESTS);
- fprintf(stderr, "-v : verbose\n");
- exit(EXIT_FAILURE);
- }
- }
- diffs = alloca( sizeof(long) * (samples + 2)); /* add 2 for off by one errors */
- /* collect test data */
- for ( i = 0 ; i < samples; i++ ) {
- struct timespec now, now1, sleep, sleep1;
- (void)clock_gettime(CLOCK_REALTIME, &now);
- (void)clock_gettime(CLOCK_REALTIME, &now1);
- diffs[i] = now1.tv_nsec - now.tv_nsec;
- if ( now1.tv_sec != now.tv_sec ) {
- /* clock roll over, fix it */
- diffs[i] += 1000000000; /* add one second */
- }
- /* instead of hammering, sleep between tests, let the cache get cold */
- sleep.tv_sec = 0;
- sleep.tv_nsec = delay; /* sleep delay */
- /* sleep1 unused, should not be returning early */
- nanosleep(&sleep, &sleep1);
- }
- /* analyze test data */
- /* print diffs, calculate min and max */
- for ( i = 0 ; i < samples; i++ ) {
- if ( verbose > 0 ) {
- printf("diff %ld\n", diffs[i]);
- }
- sum += diffs[i];
- if ( diffs[i] < min ) min = diffs[i];
- if ( diffs[i] > max ) max = diffs[i];
- }
- mean = sum / (samples - 1);
- qsort( diffs, samples, sizeof(long), compare_long);
- median = diffs[(samples / 2) + 1];
- for ( i = 0 ; i < samples; i++ ) {
- stddev += pow(diffs[i] - mean, 2);
- }
- stddev = sqrt(stddev/samples);
- printf("samples %d, delay %ld ns\n", samples, delay);
- printf("min %ld ns, max %ld ns, mean %ld ns, median %ld ns, StdDev %ld ns\n",
- min, max, mean, median, (long)stddev);
- }
|