The attached code tried two loops each of which just calls a function that increments an integer variable. One loop is a simple variable, the other has the thread_local qualifier. I put in ugly annotations to prevent g++ from inlining the functions even though I compile with -O3, but in real cases separate compilation forces each TL access to be independent. The timing as between the two cases is EXTREME on cygwin (both 32 and 64-bit) however g++ on Linux and the Microsoft compiler on Windows both manage to keep the base of thread-local regions in a segment register in such a way that the thread_local overhead is minimal. The cygwin thread_local overhead is large enough to be very visible in my code as a whole. I can see that changing to use a segment register might be a painful API change even if it was feasible, but has there been any consideration of it? Note that x86_64-w64-mingw32-g++ and clang also do not use the segment register so suffer the significant speed penalty, so maybe it would be hard to match what Microsoft manage?

Sample output:
    simple 1.265
    thread_local 33.219


           Arthur
#include <time.h>
#include <iostream>
thread_local int tl_var = 0;
int simple_var = 0;
void simple_inc() __attribute__ ((noinline));
void simple_inc()
{   simple_var++;
}
void tl_inc() __attribute__ ((noinline));
void tl_inc()
{   tl_var++;
}
int main(int argc, char *argv[])
{   clock_t c0 = clock();
    for (unsigned int i=0; i<0x40000000; i++) simple_inc();
    std::cout << "simple " << ((clock()-c0)/(double)CLOCKS_PER_SEC)
              << std::flush << std::endl;
    c0 = clock();
    for (unsigned int i=0; i<0x40000000; i++) tl_inc();
    std::cout << "thread_local " << ((clock()-c0)/(double)CLOCKS_PER_SEC)
              << std::flush << std::endl;
    return 0;
}
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to