none
degrated performance in multithread application

    Question

  • Hi,

    I have a multithread application for working with a lot of data. In VS 2010 the performance was ok. Now I switch to VS 2015 update 2 and the performance is very bad. The runtime of the appllications is about 3 times longer. On profiling I found the problem in some functions like atoi, isdigit or isspace. After code review of the runtime library I found the problem in the function __crt_interlocked_compare_exchange. This function calls InterlockedCompareExchange. This call is only done, when no locale is specified. After I rewrite my code to use the "_l"-functions like _atoi_l, _isdigit_l or _isspace_l the performance is very good. But I can only rewrite the use of C-Runtime functions. If I use STL (std::iscpace), these functions calling the C-Runtime without locale. Now my question.
    Is there any suggestion, to use always the functions with locale? Or is there any other way to improve the perfomance?

    Wednesday, January 25, 2017 1:37 PM

Answers

All replies

  • Hi friend,

    Welcome to MSDN forum.

    Parallel compilation is off by default in VS2015, please turn it on, and please be sure to select All Configurations and All Platforms before making this change, shown in the following snapshot:

    If we build the debug configuration now we will get an error because Enable Minimal Rebuild is on by default and it is incompatible with multi-processor compilation. We need to turn it off. Again, be sure to select All Configurations and All Platforms before making this change:

    Please give it a try and I hope works.  And please mark a reply as answer if it will have helped resolved your doubts. Thanks for your cooperation:)

    Have a nice day.

    Best regards,

    Fletcher


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, January 26, 2017 11:06 AM
  • thank you for your reply, but my problemis not the build-process. I build my application with gnu-make. My problem is the performance of the release build.

    Here is a sample sourcecode:

    #include <windows.h>
    #include <ctype.h>
    #include <locale.h>
    #include <process.h>
    #include <stdio.h>

    static _locale_t s_locale = _get_current_locale();

    unsigned __stdcall
    Worker1( void * )
    {
        const char * testStr = "1234567890";
        size_t testStrLen = strlen(testStr);
        for ( size_t idx = 0; idx < 5000000; ++idx ) {
            for ( size_t idx2 = 0; idx2 < testStrLen; ++idx2 ) {
                isdigit( testStr[ idx2 ] );
            }
        }
        return 0;
    }

    unsigned __stdcall
    Worker2( void * )
    {
        const char * testStr = "1234567890";
        size_t testStrLen = strlen(testStr);
        for ( size_t idx = 0; idx < 5000000; ++idx ) {
            for ( size_t idx2 = 0; idx2 < testStrLen; ++idx2 ) {
                _isdigit_l( testStr[ idx2 ], s_locale );
            }
        }
        return 0;
    }

    int main( int argc, const char ** argv )
    {
        HANDLE threads1[ 10 ];
        HANDLE threads2[ 10 ];
        LARGE_INTEGER startTime;
        QueryPerformanceCounter( &startTime );

        for ( size_t idx = 0; idx < 10; ++idx ) {
            threads1[idx] = (HANDLE)_beginthreadex( NULL, 0, Worker1, nullptr, 0, NULL );
        }
        WaitForMultipleObjects( 10, threads1, true, INFINITE );

        LARGE_INTEGER runTime;
        QueryPerformanceCounter( &runTime );
        runTime.QuadPart -= startTime.QuadPart;
        printf( "Runtime: %I64d\n", runTime.QuadPart );

        QueryPerformanceCounter( &startTime );
        for ( size_t idx = 0; idx < 10; ++idx ) {
            threads2[idx] = (HANDLE)_beginthreadex( NULL, 0, Worker2, nullptr, 0, NULL );
        }
        WaitForMultipleObjects( 10, threads2, true, INFINITE );

        QueryPerformanceCounter( &runTime );
        runTime.QuadPart -= startTime.QuadPart;
        printf( "Runtime: %I64d\n", runTime.QuadPart );
    }

    Compileoptions:

    "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/bin/amd64_x86/cl.exe /Foobj/vs2015performance.obj /c /nologo /EHa /MD /GR /W3 /GF /DWIN32 /w34702 /D_WIN32_WINNT=0x0501 /DNTDDI_VERSION=0x05010300 /Z7 /DNODEBUG /DNDEBUG /O2 /GL /Zp4    -I"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/include -I"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/atlmfc/include -I"C:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/ucrt" -I"C:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/um" -I"C:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/shared" vs2015performance.cpp

    Linkeoptions:

    "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/bin/amd64_x86/link.exe /OUT:../bin/testprj.exe /NOLOGO /NODEFAULTLIB /INCREMENTAL:NO /NXCOMPAT:NO /MANIFEST /SUBSYSTEM:CONSOLE",5.02" /LTCG /MAP:../bin/testprj.map /PDB:../bin/testprj.pdb   obj/vs2015performance.obj     /LIBPATH:"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/lib /LIBPATH:"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"/atlmfc/lib /LIBPATH:"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/ucrt/x86" /LIBPATH:"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/um/x86" version.lib gdi32.lib user32.lib comdlg32.lib advapi32.lib shell32.lib odbc32.lib odbccp32.lib ws2_32.lib msvcrt.lib msvcprt.lib oldnames.lib kernel32.lib vcruntime.lib ucrt.lib legacy_stdio_definitions.lib legacy_stdio_wide_specifiers.lib

    In release build the time spent in Worker1 is more then two times more then in Worker2.

    Thursday, January 26, 2017 11:20 AM
  • Hi Hardy Braunsdorf,

    Please run worker1 and worker2 separately to see the results.

    Sincerely,

    Oscar


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, January 27, 2017 2:51 AM
    Moderator
  • Worker1 and Worker2 run separately, see line 45 of the source code.

    Hardy

    Friday, January 27, 2017 7:50 AM
  • Hi Hardy,

    Please set Runtime Library as MT in VS2015 and give a try:

    Hope it works.

    Best regards,

    Fletcher


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, January 30, 2017 3:18 PM
  • Hi,

    I found the solution. Simple linking threadlocale.obj to the target.

    Hardy

    Monday, January 30, 2017 3:22 PM
  • Hi Hardy,

    Glad to hear that you've resolved it, that's great. Would you please mark your reply as answer which could be beneficial to other members.

    Best regards,

    Fletcher


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, January 30, 2017 3:44 PM