CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Oct 2015
    Posts
    5

    strange performance behavior in character functions: toupper, tolower, isalpha, ...

    In our MFC application, one of our dll will call "tolower" frequently. Here is the sample code:

    void foo(char c)
    {
    for(int i=0;i<200000;++i)
    {
    aaa += tolower(c);
    }
    }

    I found that there is a very stranger behavior:
    1) The tolower function only slow the performance signifcantly when foo is called in the thread of the main process.
    if we fork a subprocess, then create a thread to call the function foo, it works fine.
    2) The release version is even much slower than the debug version.

    I have tested toupper, tolower, isalpha, islower. The same phenomenon will be observed.
    But if I change to function sin, it works as fast as running with subprocess

    I am using VS2012, MFC.

  2. #2
    Join Date
    Jun 2015
    Posts
    208

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Quote Originally Posted by u11072940 View Post
    I found that there is a very stranger behavior:
    It could be due to different overhead depending on how functions are called.

    Slowest would be if a function is called over a dynamically linked interface, faster would be if the function is statically linked and the call resolved at compiletime, and fastest would be if the function isn't called at all but inlined.

    So for fastest code, try to ensure that frequently called small functions are inlined.
    Last edited by tiliavirga; October 3rd, 2015 at 01:55 AM.

  3. #3
    Join Date
    Oct 2015
    Posts
    5

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Thanks tiliavirga.

    What confuse me is that :

    if I change

    aaa += tolower(c);

    to

    aaa += toupper(c); //or isalpha(c), isdigit(c)

    the performance issue still can be observed.

    But if I change it to
    aaa += sin(c);

    it works fine

  4. #4
    Join Date
    Oct 2008
    Posts
    1,456

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    it looks like you have a global locale requiring sychronization, possibly explaining the observed slowdown.

    Did you try stepping through tolower() code ?
    Did you try the std::tolower version passing a specific local locale ( pun intended ) ?

  5. #5
    Join Date
    Jun 2015
    Posts
    208

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Quote Originally Posted by u11072940 View Post
    What confuse me is that :
    If my assumption is correct than an explanation for this behaviour could be that since tolower() and sin() are on different include files they may be linked differently to the program.

    A long shot maybe but I've seen weirder stuff in my day.

  6. #6
    Join Date
    Oct 2015
    Posts
    5

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Quote Originally Posted by superbonzo View Post
    it looks like you have a global locale requiring sychronization, possibly explaining the observed slowdown.

    Did you try stepping through tolower() code ?
    Did you try the std::tolower version passing a specific local locale ( pun intended ) ?

    Thanks superbonzo, you're right
    after step into tolower, its implementation is:

    <tolower.cpp>
    extern "C" int __cdecl tolower (
    int c
    )
    {

    if (__locale_changed == 0)
    {
    return __ascii_towlower(c); //this is assembly code, fast
    }
    else
    {
    return _tolower_l(c, NULL); //slow
    }
    }


    if I change tolower to _tolower_l, now running in subprocess will be as slow as running in main process

    From the phenomenon:
    it seems that if running in the thread of main process, the __locale_changed will be 1.
    while running in the thread of subprocess, __locale_changed will be 0.
    I am wondering why ?
    Last edited by u11072940; October 5th, 2015 at 12:08 PM.

  7. #7
    Join Date
    Oct 2015
    Posts
    5

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Yes, sin function is in math.h

    <math.h>
    inline float __CRTDECL sin(_In_ float _X)
    {return (sinf(_X)); } //assembly code

    while tolower is in <tolower.cpp>

  8. #8
    Join Date
    Oct 2008
    Posts
    1,456

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    Quote Originally Posted by u11072940 View Post
    I am wondering why ?
    I guess you set a global locale somewhere (either in your DLL, or in the main process or in some other DLL, assuming the runtime linked dynamically everywhere ) frequently accessed by multiple threads, hence causing a slowdown due to excessive lock contention. The forked process will have its own runtime, hence its own possibly default C locale ( that is optimized as you noted ).

    Concerning a solution and assuming you don't actually need a locale, you could use the locale aware tolower version defined in <locale> as previously suggested; eg. std:: tolower( c, std:: locale:: classic() )

  9. #9
    Join Date
    Oct 2015
    Posts
    5

    Re: strange performance behavior in character functions: toupper, tolower, isalpha,

    It works, Thanks!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured