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.
Re: strange performance behavior in character functions: toupper, tolower, isalpha,
Quote:
Originally Posted by
u11072940
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.
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
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 :) ) ?
Re: strange performance behavior in character functions: toupper, tolower, isalpha,
Quote:
Originally Posted by
u11072940
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.
Re: strange performance behavior in character functions: toupper, tolower, isalpha,
Quote:
Originally Posted by
superbonzo
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 ?
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>
Re: strange performance behavior in character functions: toupper, tolower, isalpha,
Quote:
Originally Posted by
u11072940
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() )
Re: strange performance behavior in character functions: toupper, tolower, isalpha,