Re: Reduce timing overhead of EXPLAIN ANALYZE using rdtsc?

Lukas Fittl <lukas@fittl.com>

From: Lukas Fittl <lukas@fittl.com>
To: Andres Freund <andres@anarazel.de>
Cc: John Naylor <johncnaylorls@gmail.com>, Jakub Wartak <jakub.wartak@enterprisedb.com>, Hannu Krosing <hannuk@google.com>, Robert Haas <robertmhaas@gmail.com>, Pavel Stehule <pavel.stehule@gmail.com>, vignesh C <vignesh21@gmail.com>, Michael Paquier <michael@paquier.xyz>, Ibrar Ahmed <ibrar.ahmad@gmail.com>, Maciek Sakrejda <m.sakrejda@gmail.com>, pgsql-hackers <pgsql-hackers@postgresql.org>, David Geier <geidav.pg@gmail.com>
Date: 2026-04-07T18:24:20Z
Lists: pgsql-hackers
On Tue, Apr 7, 2026 at 10:59 AM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> On 2026-04-07 00:04:51 -0700, Lukas Fittl wrote:
> > Attached v22 with documentation updates. I've also marked the ARM
> > patch "nocfbot" for now, so its clear we're doing that one later.
>
> - changed comment in InitProcessGlobals to be consistent with other cases
> - added a comment to the fallthrough to the generic logic in x86_tsc_frequency_khz
> - started to wonder if we ought to report
>          * The similar __get_cpuid_count function does not work as expected since
>          * it contains a check for __get_cpuid_max, which has been observed to be
>   as a bug.  That's obviously independent of committing this.
>
> - a few typos (s/possibly/possible/, s/its/it's/, s/\. are/. Are/,
>   INSTR_TIME_ADD_NANOSEC comment variable names) found with modern spell
>   checking tools (i.e. an ai review)
>
> - fixed include order in guc_tables.c
>
> - slight rephrasing of pg_initialize_timing() comment about
>   pg_set_timing_clock_source()
>
> - Moved the indexterm to the relevant paragraphs. I don't think it really
>   matters, but it seemed a tad clearer
>
> - shortened some commit message titles ;)
>
> - Added a comment about why always_inline is needed for pg_get_ticks, and as
>   part of that swapped _fast() and plain versions around.
>
> - I'm somewhat tired, because I was wondering whether TSC_CALIBRATION_SKIPS
>   should be a power of 2, to make the check faster. But uh, IT DOESN'T MATTER
>   :)
>
> I've pushed 0001, 0002, 0003.

Yay! Thank you for pushing :)

And thank you everyone on this thread for countless reviews, and to
David for writing some essential parts of this earlier.

*cautiously pours a celebratory beverage*

>
> There's one minor documentation issue in 0004 that I wanted to look at before
> pushing (and I need to switch to something else for a bit).  The rephrasing
> gets rid of
>
> -   [...] , with the worst case somewhere between 32768 and
> -   65535 nanoseconds.  In the second block, we can see that typical loop
> -   time is 16 nanoseconds, and the readings appear to have full nanosecond
> -   precision.
>
> I don't mind loosing the first sentence, but the second one might be useful to
> somebody?

Hm, yeah, you're right. What if we word like this:

  <para>
   The example results below show system clock timing where 99.99% of loops
   took between 16 and 63 nanoseconds.  In the second block, we can see that
   the typical loop time is 40 nanoseconds, and the readings appear to have
   full nanosecond precision.  Following the system clock results, the
   <acronym>TSC</acronym> clock source results are shown.  The
   <command>RDTSCP</command> instruction shows most loops completing in
   20&ndash;30 nanoseconds, while the <command>RDTSC</command> instruction
   is the fastest with an average loop time of 20 nanoseconds.  In this
   example the <acronym>TSC</acronym> clock source will be used by default,
   but can be disabled by setting <varname>timing_clock_source</varname> to
   <literal>system</literal>.
  </para>


Thanks,
Lukas

--
Lukas Fittl



Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. pg_test_timing: Show additional TSC clock source debug info

  2. instrumentation: Avoid CPUID 0x15/0x16 for Hypervisor TSC frequency

  3. pg_test_timing: Also test RDTSC[P] timing, report time source, TSC frequency

  4. Allow retrieving x86 TSC frequency/flags from CPUID

  5. instrumentation: Standardize ticks to nanosecond conversion method

  6. instrumentation: Use Time-Stamp Counter on x86-64 to lower overhead

  7. Check for __cpuidex and __get_cpuid_count separately

  8. pg_test_timing: Reduce per-loop overhead

  9. Refactor handling of x86 CPUID instructions

  10. instrumentation: Drop INSTR_TIME_SET_CURRENT_LAZY macro

  11. Rename pg_crc32c_sse42_choose.c for general purpose

  12. Zero initialize uses of instr_time about to trigger compiler warnings

  13. instr_time: Represent time as an int64 on all platforms

  14. Add 250c8ee07ed to git-blame-ignore-revs