View Issue Details

IDProjectCategoryView StatusLast Update
0016600CentOS-7glibcpublic2020-10-09 08:15
Reporterek1010 Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionwon't fix 
Product Version7.7-1908 
Summary0016600: chrono call is much slower than clock_gettime
DescriptionCentOS 7 appears to have std::chrono calls as much slower than gettimeofday or clock_gettime direct calls.

$ ./a.out 100000
loops: 100000
getTimeOfDay(): 4 milliseconds
chrono: 49 milliseconds
clock_gettime(CLOCK_REALTIME): 3 milliseconds
clock_gettime(CLOCK_MONOTONIC): 3 milliseconds
Steps To ReproduceSample program to reproduce:
#include <iostream>
#include <unistd.h> /* POSIX flags */
#include <time.h> /* clock_gettime(), time() */
#include <sys/time.h> /* gethrtime(), gettimeofday() */
#include <sys/resource.h> /*cputime*/
#include <sys/times.h> /*cputime*/
#include <chrono>

using namespace std;

double getTimeOfDay() {
        /* POSIX. --------------------------------------------------- */
        struct timeval tm;
        gettimeofday(&tm, NULL);
        return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
}

int main(int argc, char *argv[]) {
        double wallTimeMultiplier = 1000000.0;

        int N = 10000;
        if(argc > 1) {
            N = atoi(argv[1]);
        }
        std::cout << "loops: " << N << std::endl;

        auto start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < N; ++i) {
                double x = getTimeOfDay();
                std::chrono::microseconds microseconds((long long)(x * wallTimeMultiplier));
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "getTimeOfDay(): " << dt.count() << " milliseconds" << std::endl;

        start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < N; ++i) {
                auto now = std::chrono::high_resolution_clock::now();
        }
        end = std::chrono::high_resolution_clock::now();
        dt = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "chrono: " << dt.count() << " milliseconds" << std::endl;

        start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < N; ++i) {
                struct timespec tv;
                clock_gettime(CLOCK_REALTIME, &tv);
                double thistime = (long) tv.tv_sec * 1000000000 + tv.tv_nsec;
        }
        end = std::chrono::high_resolution_clock::now();
        dt = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "clock_gettime(CLOCK_REALTIME): " << dt.count() << " milliseconds" << std::endl;

        start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < N; ++i) {
                struct timespec tv;
                clock_gettime(CLOCK_MONOTONIC, &tv);
                double thistime = (long) tv.tv_sec * 1000000000 + tv.tv_nsec;
        }
        end = std::chrono::high_resolution_clock::now();
        dt = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "clock_gettime(CLOCK_MONOTONIC): " << dt.count() << " milliseconds" << std::endl;

        return 0;
}
TagsNo tags attached.
abrt_hash
URL

Activities

gnaggnoyil

gnaggnoyil

2020-09-28 06:06

reporter   ~0037742

The cause of this issue is that CentOS 7's libstdc++ uses syscall `SYS_clock_gettime` rather than glibc's `clock_gettime` for `std::chrono::system_clock::now` and `std::chrono::high_resolution_clock::now`. The syscall one is much slower than the glibc onc since the glibc one does not need to invoke a syscall usually.

However, I still consider it a bug as according to this gcc mailing list(https://gcc.gnu.org/legacy-ml/gcc-help/2014-01/msg00093.html), libstdc++ should automatically choose to use the glibc one if the linked glibc has version 2.17 or greater. And glibc version of CentOS7 is just 2.17, which means libstdc++ should be built with the glibc one selected rather than the syscall one.

FYI, command `/lib64/libc.so.6` shows:

```
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.5 20150623 (Red Hat 4.8.5-39).
Compiled on a Linux 3.10.0 system on 2020-03-31.
Available extensions:
        The C stubs add-on version 2.1.2.
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
        RT using linux kernel aio
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
```

and command `egrep -r "_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL" /usr/include/c++/4.8.5` shows:

```
/usr/include/c++/4.8.5/x86_64-redhat-linux/32/bits/c++config.h:#define _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL 1
/usr/include/c++/4.8.5/x86_64-redhat-linux/bits/c++config.h:#define _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL 1
/usr/include/c++/4.8.5/x86_64-redhat-linux/bits/c++config.h:#define _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL 1
```
ManuelWolfshant

ManuelWolfshant

2020-09-28 19:30

manager   ~0037743

CentOS is a rebuild of the sources used to create RHEL and aims to reproduce RHEL bug for bug and feature for feature. Please submit your request to Redhat via bugzilla.redhat.com and if/when RH accepts it and incorporates it into RHEL and releases a patched version, then CentOS will pick it up automatically.
For easier tracking, please crosslink this bug with the one opened at bugzilla.redhat.com.
gnaggnoyil

gnaggnoyil

2020-10-09 05:56

reporter   ~0037802

Oops, just found out this GCC bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59177#c6 , and it seems to indicate that faster `std::chrono` implementation will not be automatically selected during configutation unless GCC version is higher than or equal to 4.9

Therefore the behavior described in this thread is just expected and this thread should be closed. Users who want faster `std::chrono` implementation should install devtoolset packages and link their corresponding libstdc++ then.
ManuelWolfshant

ManuelWolfshant

2020-10-09 08:14

manager   ~0037803

thank you for the investigation and notifying us

Issue History

Date Modified Username Field Change
2019-10-16 00:18 ek1010 New Issue
2020-09-28 06:06 gnaggnoyil Note Added: 0037742
2020-09-28 19:30 ManuelWolfshant Note Added: 0037743
2020-10-09 05:56 gnaggnoyil Note Added: 0037802
2020-10-09 08:14 ManuelWolfshant Note Added: 0037803
2020-10-09 08:15 ManuelWolfshant Status new => closed
2020-10-09 08:15 ManuelWolfshant Resolution open => won't fix