On Fri, Sep 08, 2023 at 09:13:24 -0700, Bill Unruh wrote: > Are you sure there is any point in nanosecond reporting?
Am I sure? No :) > Ie, I would suspect that the uncertainty in those times is at best > microsecond anyway, so nanosecond reporting is unwarrented accuracy. (Ie, > it takes a microsecond to determine the local clock time anyway) Correct me if I'm wrong, but getting the local clock should be constant-ish offset and therefore regardless of how long it takes, it is not a matter of accuracy. I just did a quick benchmark to see how long clock_gettime() takes on my ~10 year old desktop running FreeBSD. It collects 100k samples, each sample being the average time for a clock_gettime in a sequence of 30 back-to-back calls. (I veried the disassembly, and the calls are all there.) Code is attached. When I run it, I get: min/avg/max 38.419355/38.613522/709.741935 ns/clock_gettime The max varies a bit between 500-ish and 700-ish ns, but the min is always in low 38s, and the average just a hair higher than the min. The CPU runs at 3.1GHz, so 39ns is about 120 cycles. That's plenty to call a function, get the hardware TSC, convert it to time-of-day, and return. Modern unix/linux is quite fast when it comes to calculating the time. I don't know how accurate clock_gettime is, but it certainly seems to have the resolution with minimal cost. Jeff.
#include <time.h> #include <stdint.h> #include <stdio.h> #define NSAMPLES 100000 #define BAD_SAMPLE 1e6 /* ignore all samples > 1ms */ #define CLOCK CLOCK_MONOTONIC static double measure(void) { struct timespec a,b,c; uint64_t start, end; double avg; asm volatile(""); clock_gettime(CLOCK, &a); asm volatile(""); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); clock_gettime(CLOCK, &b); asm volatile(""); clock_gettime(CLOCK, &c); asm volatile(""); start = a.tv_sec * 1000000000 + a.tv_nsec; end = c.tv_sec * 1000000000 + c.tv_nsec; avg = (end - start) / 31.; //printf("%19lu - %19lu = %6ld => %f\n", start, end, end - start, avg); return avg; } int main(int argc, char **argv) { double min, max, avg; int nsamples; int i; min = 1e9; max = 0; avg = 0; nsamples = 0; for (i = 0; i < NSAMPLES; i++) { double sample; sample = measure(); if (sample > BAD_SAMPLE) continue; if (min > sample) min = sample; if (max < sample) max = sample; avg += sample; nsamples++; } avg /= nsamples; printf("%d samples\n", nsamples); printf("min/avg/max %f/%f/%f ns/clock_gettime\n", min, avg, max); printf("avg - min = %f ns\n", avg - min); return 0; }