Re: Reduce timing overhead of EXPLAIN ANALYZE using rdtsc?
Lukas Fittl <lukas@fittl.com>
Attachments
- v15-0001-Check-for-HAVE__CPUIDEX-and-HAVE__GET_CPUID_COUN.patch (application/octet-stream) patch v15-0001
- v15-0004-pg_test_timing-Also-test-RDTSC-RDTSCP-timing-and.patch (application/octet-stream) patch v15-0004
- v15-0003-instrumentation-Use-Time-Stamp-Counter-TSC-on-x8.patch (application/octet-stream) patch v15-0003
- v15-0002-instrumentation-Streamline-ticks-to-nanosecond-c.patch (application/octet-stream) patch v15-0002
- v15-0005-instrumentation-ARM-support-for-fast-time-measur.patch (application/octet-stream) patch v15-0005
On Wed, Apr 1, 2026 at 7:18 PM John Naylor <johncnaylorls@gmail.com> wrote:
> -# Check for __get_cpuid_count() and __cpuidex() in a similar fashion.
> +# Check for __get_cpuid_count() and __cpuidex() separately, since we sometimes
> +# need __cpuidex() even if __get_cpuid_count() is available.
>
> I'm not sure we need to document here that we need them separately. It
> seems more important to do that for the __cpuidex helper that's in a
> later patch. I don't feel strongly, though.
>
> I'd probably just do
>
> # Check for __get_cpuid_count()
> ...
>
> # Check for __cpuidex()
> ...
>
> Either way, we do need a space between separate tests (ditto Meson).
Makes sense, updated.
>
> +if cc.links('''
> + #ifdef _MSC_VER
> #include <intrin.h>
> + #else
> + #include <cpuid.h>
> + #endif
> int main(int arg, char **argv)
> {
> - unsigned int exx[4] = {0, 0, 0, 0};
> + int exx[4] = {0, 0, 0, 0};
> __cpuidex(exx, 7, 0);
> }
>
> Hmm, maybe we can declare unsigned and cast to signed for MSVC as we
> do where the code is used.
Sure, I think it works either way - updated.
>
> +# __cpuidex()
> +AC_CACHE_CHECK([for __cpuidex], [pgac_cv__cpuidex],
> +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#ifdef _MSC_VER
> + #include <intrin.h>
> + #else
> + #include <cpuid.h>
> + #endif],
> + [[int exx[4] = {0, 0, 0, 0};
> + __cpuidex(exx, 7, 0);
> + ]])],
> + [pgac_cv__cpuidex="yes"],
> + [pgac_cv__cpuidex="no"])])
> +if test x"$pgac_cv__cpuidex" = x"yes"; then
> + AC_DEFINE(HAVE__CPUIDEX, 1, [Define to 1 if you have __cpuidex.])
> fi
>
> MSVC doesn't use autoconf, so we can leave out the intrin.h and keep
> using unsigned int.
I think that might be a problem for Clang on Windows, which has MSVC
compatibility headers, and will set _MSC_VER, see [0] and [1].
It probably works in practice, but it seems better to match the
autoconf checks to the actual code?
>
> -#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT)
> -#include <cpuid.h>
> -#endif
> -
> -#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX)
> +#if defined(HAVE__CPUID) || defined(HAVE__GET_CPUID) ||
> defined(HAVE__GET_CPUID_COUNT) || defined(HAVE__CPUIDEX)
> +#if defined(_MSC_VER)
> #include <intrin.h>
> +#else
> +#include <cpuid.h>
> +#endif /* defined(_MSC_VER) */
> #endif
>
> Now I'm thinking at least one of these will be defined, otherwise we'd
> have an #error, so we can just gate solely on _MSC_VER.
Yeah, makes sense, we would fail to compile in that case anyway.
I'm attaching v15 rebased, with the above changes made to 0001 to
unblock things, but feedback by Andres not addressed yet (will work on
that tomorrow).
John, feel free to adjust as you see fit in case there is any other
minor aspects to fix.
Thanks,
Lukas
[0]: https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
[1]: https://clang.llvm.org/doxygen/intrin_8h_source.html
--
Lukas Fittl
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
pg_test_timing: Show additional TSC clock source debug info
- 5ba34f6dc838 19 (unreleased) landed
-
instrumentation: Avoid CPUID 0x15/0x16 for Hypervisor TSC frequency
- 7fc36c5db550 19 (unreleased) landed
-
pg_test_timing: Also test RDTSC[P] timing, report time source, TSC frequency
- 16fca4825483 19 (unreleased) landed
-
Allow retrieving x86 TSC frequency/flags from CPUID
- bcb2cf41f964 19 (unreleased) landed
-
instrumentation: Standardize ticks to nanosecond conversion method
- 0022622c93d9 19 (unreleased) landed
-
instrumentation: Use Time-Stamp Counter on x86-64 to lower overhead
- 294520c44487 19 (unreleased) landed
-
Check for __cpuidex and __get_cpuid_count separately
- effaa464afd3 19 (unreleased) landed
-
pg_test_timing: Reduce per-loop overhead
- 82c0cb4e672d 19 (unreleased) landed
-
Refactor handling of x86 CPUID instructions
- be6a7494d2e3 19 (unreleased) landed
-
instrumentation: Drop INSTR_TIME_SET_CURRENT_LAZY macro
- 9d6294c09ed0 19 (unreleased) landed
-
Rename pg_crc32c_sse42_choose.c for general purpose
- b9278871f991 19 (unreleased) cited
-
Zero initialize uses of instr_time about to trigger compiler warnings
- 25b2aba0c3a5 16.0 landed
-
instr_time: Represent time as an int64 on all platforms
- 03023a2664f8 16.0 landed
-
Add 250c8ee07ed to git-blame-ignore-revs
- ff23b592ad66 16.0 cited