summaryrefslogtreecommitdiff
path: root/contrib/clock_test.c
diff options
context:
space:
mode:
authorGary E. Miller <gem@rellim.com>2018-01-25 17:15:20 -0800
committerGary E. Miller <gem@rellim.com>2018-01-25 17:15:20 -0800
commit598b8b9bc743ac3f03e0580be9fd222b4412a469 (patch)
tree3e4c3c600b16e17455f88e887a7c51b71a94b22f /contrib/clock_test.c
parent686e72cb3a29fa227758aabf63d6f79c5fea84ae (diff)
downloadgpsd-598b8b9bc743ac3f03e0580be9fd222b4412a469.tar.gz
Add clock_test in contrib.
clock_test checks the latency of the clock_gettime() system call.
Diffstat (limited to 'contrib/clock_test.c')
-rw-r--r--contrib/clock_test.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/contrib/clock_test.c b/contrib/clock_test.c
new file mode 100644
index 00000000..904c9678
--- /dev/null
+++ b/contrib/clock_test.c
@@ -0,0 +1,110 @@
+/*
+ * clock_test. A simple program to test the latency of the clock_gettime() call
+ *
+ * Compile: gcc clock_test.c -lm -o clock_test
+ *
+ */
+
+#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);
+}