[PATCH grout] add high-performance clock
Morten Brørup
mb at smartsharesystems.com
Thu Jun 18 11:16:23 CEST 2026
> From: Robin Jarry [mailto:rjarry at redhat.com]
> Sent: Thursday, 18 June 2026 10.17
>
> Morten Brørup, Jun 17, 2026 at 13:44:
> > That's what I thought too, when I submitted the initial patch
> (Tuesday
> > 9th).
> >
> > But further experimentation showed that
> > clock_gettime(CLOCK_MONOTONIC_RAW) and rte_rdtsc() (divided by
> > rte_get_tsc_hz()) are not in sync, not even when the clocksource is
> > "tsc".
> >
> > They are not only offset by a different epoch (which I thought), they
> > also drift differently (which came as a surprise to me). On a VMware
> > virtual machine, I saw them drifting a few seconds further apart
> > overnight.
> >
> > It seems there is no simple way to convert between these two clocks,
> > just like there is no way to convert between CLOCK_MONOTONIC_RAW and
> > CLOCK_MONOTONIC.
>
> OK good to know.
>
> > Train of thought:
> >
> > For now, Grout uses the timestamps for e.g. ageing in the bridge FDB,
> > which doesn't require a high-res clock. I could add a low-accuracy
> > clock based on CLOCK_MONOTONIC (which is NTP adjusted), and use that
> > for timestamping the FDB entries. It would be somewhat similar to my
> > suggestion about adding support for CLOCK_REALTIME (Saturday 13th).
> >
> > With such a change, CLOCK_MONOTONIC would replace CLOCK_MONOTONIC_RAW
> > as the "common clock across all processes", and gr_clock_ns() would
> go
> > back to being a wrapper around clock_gettime(), but now using
> > CLOCK_MONOTONIC instead of CLOCK_MONOTONIC_RAW.
> >
> > But only provides a solution for low-res clocks.
> >
> > The root cause is that we are mixing time intervals (e.g. last seen
> > "60 seconds ago") with timestamps (e.g. last seen "17-JUN-2026
> > 13:18:00 CEST"). We do this, because we have to. E.g. we put
> > a timestamp on an FDB entry, so we can calculate its age (the time
> > interval).
>
> Low-res clocks are perfectly fine for this use case.
Agree.
> I imagine that high
> res clocks would be only useful for datapath only operations where the
> timestamps don't need to be exposed to the API (QoS, L4S, etc.).
>
> What about keeping the high res clocks only internal to grout and use
> CLOCK_MONOTONIC_RAW (not affected by NTP) for low res timestamps that
> are eventually exposed to the user?
I can foresee a future where high-res clocks also become relevant for the API.
E.g. for RTT measurements (PING and SYN-ACK), and for PCAP time stamps.
>
> If performance in the datapath is a concern, we could keep a per-worker
> cached value that is only updated every housekeeping interval like
> I had outlined here:
>
> https://inbox.dpdk.org/grout/DIP6E2Y6CLJY.26JKOONI7DQGD@redhat.com/
>
> > Another solution would be to convert between relevant clock domains
> at
> > the API border. But we might extend the API border with shared memory
> > for accessing very large tables, which may contain entries with Grout
> > timestamps. If so, the non-Grout process needs to understand Grout's
> > clock domain, to be able to convert to its own clock domain.
> >
> > The solution I had proposed - making gr_clock_ns() a client API
> > - solves this challenge: The API allows reading Grout's clock through
> > gr_clock_ns(), so the non-Grout application can calculate the age of
> > an entry by subtracting the entry's timestamp from the return value
> of
> > gr_clock_ns(). And if it needs a wall clock timestamp of the entry,
> it
> > can subtract the age from the return value of
> > clock_gettime(CLOCK_REALTIME).
>
> Honestly, I don't like the idea of querying the API to get a "timestamp
> value" to be able to compute time intervals from API messages that we
> just received. This feels redundant. The conversion (if any) should be
> done by grout before sending the first message.
Yes, it does feel redundant.
Currently, all API reads go via accessor functions in Grout, so the accessor function in Grout can do the clock domain conversion. That would be no problem.
However, imagine a future where another type of API for reading very large tables is added to Grout, where the client has direct read access to shared memory provided by (and updated by) Grout.
Here's an example from real life: An ISP shaper with per-subscriber statistics being updated in the dataplane, and being read once per second by a client performing statistics analysis. With 16 64-bit fields and 64k subscribers, that's 8 MB/s. We certainly don't want that going via an accessor function and the API's UNIX domain socket.
If we don't want the client doing the clock domain conversion, Grout's dataplane would need to maintain redundant time stamps in such shared memory; one internal to Grout and one for the API. And that moves the redundancy to the dataplane.
Delegating the clock domain conversion to the client also has its advantages: The client decides which clock domain it wants to expose to the user, CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC, or CLOCK_REALTIME.
>
> --
> Robin
>
> > Might not be suitable for persons suffering from weak hearts.
More information about the grout
mailing list