Discussion:
Why does std::chrono now() uses slow syscall?
Keith Erickson
2014-01-26 07:50:16 UTC
Permalink
When I do this:

#include <chrono>
#include <iostream>

using Clk = std::chrono::high_resolution_clock;
int main() {
auto t1 = Clk::now();
auto t2 = Clk::now();
std::cout << "Chrono: " << (t2-t1).count() << "ns" << std::endl;
}

I get results of about 1.5us to do the clock operations. When I do
the same thing in C using clock_gettime, it's on the order of 250ns.
When I run the above code on ideone.com, I get the expected C time of
about 250ns. I traced this down to the fact that my version of
chrono.cc got compiled with _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
defined, and so I was using the absurdly slow syscall to get time
instead of the very fast clock_gettime().

My questions, then, are.... why would I ever want to use the syscall
version? It seems that configure prefers it, and will use it if it's
available. But it's stupidly slow, even on the fasted server CPU that
AMD sells (Opteron 6386 SE at the time of this writing). How do I not
use this slow method? Do I have to compile gcc specially? What are
the drawbacks to forcing configure to not set that #define? Is there
an approved way to tell configure to use a fast time?
Jonathan Wakely
2014-01-26 10:33:36 UTC
Permalink
Post by Keith Erickson
My questions, then, are.... why would I ever want to use the syscall
version? It seems that configure prefers it, and will use it if it's
available.
It prefers to use clock_gettime and only uses the syscall if a
configure test using clock_gettime(CLOCK_MONOTONIC, &tp) fails.
Post by Keith Erickson
But it's stupidly slow, even on the fasted server CPU that
AMD sells (Opteron 6386 SE at the time of this writing). How do I not
use this slow method? Do I have to compile gcc specially? What are
the drawbacks to forcing configure to not set that #define? Is there
an approved way to tell configure to use a fast time?
Prior to glibc 2.17 clock_gettime was in librt.so not libc.so, which
is not used automatically by libstdc++. To tell configure to use it
you need to build GCC with --enable-libstdcxx-time=rt, but that means
that libstdc++.so will be linked to librt.so which depends on
libpthread.so which means that the library always thinks it is part of
a multithreaded application and so even single-threaded programs use
atomic operations for internal reference-counting (e.g. in std::string
and std::shared_ptr). That's why we don't use clock_gettime unless
explicitly configured to do so.

With glibc 2.17 or later clock_gettime will be used automatically,
because the functions were moved out of librt.so.

On my Fedora 20 system I get

| #define HAVE_SYS_TIME_H 1
| #define _GLIBCXX_USE_GETTIMEOFDAY 1
| #define _GLIBCXX_USE_CLOCK_MONOTONIC 1
| #define _GLIBCXX_USE_CLOCK_REALTIME 1
| #define _GLIBCXX_USE_SCHED_YIELD 1
| #define _GLIBCXX_USE_NANOSLEEP 1

which means it doesn't need the syscall version.
Jonathan Wakely
2014-01-27 00:12:06 UTC
Permalink
So how do I use the fast clock_gettime in a single threaded program on glibc
2.12 (rhel6) without pulling in pthread?
AFAIK you can't. clock_gettime is in librt.so which depends on libpthread.so

Glibc 2.17 moved clock_gettime out of librt.so specifically to solve
this issue, because that was the only way to get clock_gettime without
depending on libpthread.so

Loading...