[PATCH] Optimize __convert_from_v when locale is already set
Brad Spencer
spencer@infointeractive.com
Tue Oct 8 14:33:00 GMT 2002
While debugging recently, I noticed that every time __convert_from_v
is called, there are expensive calls to malloc, free, strlen, strcpy,
and two possibly unnecessary extra calls to setlocale. I've added a
cheap check to see if the locale is already "C" before we get out the
hammers. I haven't address the exception safety issues raised
earlier.
I used a simple test to see if it is actually faster:
#include <iostream>
using std::cout;
int
main()
{
const int x = 12345;
for(unsigned int i = 0; i < 1000000; ++i) {
cout << x;
}
return 0;
}
$ locale
LANG=C
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=
$ test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -g -O6 -o loc main.cc
$ time ./loc >/dev/null
real 0m3.066s
user 0m3.070s
sys 0m0.000s
$ g++ -Wall -g -O6 -o loc-stock main.cc
$ time ./loc-stock >/dev/null
real 0m3.416s
user 0m3.410s
sys 0m0.000s
This seems to be harmless... Is it not? I couldn't seem to set my
locale (inside the application) no matter what I tried, so I haven't
tested opposite case to see how much it slows down (if it is at all
noticable).
I'm also curious as to whether the entire locale needs to be changed.
I take it that the character set is what is preventing just LC_NUMERIC
from being modified? Or am I just naive? :)
Patch attached.
--
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company
-------------- next part --------------
ChangeLog
2002-10-08 <spencer@infointeractive.com>
* include/bits/locale_facets.tcc (__convert_from_v): Avoid
expensive operations when C locale is already set.
*** ../../../../reference_gcc/gcc-3.2/libstdc++-v3/include/bits/locale_facets.tcc Tue Oct 8 17:48:11 2002
--- locale_facets.tcc Tue Oct 8 17:53:41 2002
*************** namespace std
*** 1977,1992 ****
{
int __ret;
char* __old = setlocale(LC_ALL, NULL);
! char* __sav = static_cast<char*>(malloc(strlen(__old) + 1));
! if (__sav)
! strcpy(__sav, __old);
! setlocale(LC_ALL, "C");
if (__prec >= 0)
__ret = snprintf(__out, __size, __fmt, __prec, __v);
else
__ret = snprintf(__out, __size, __fmt, __v);
! setlocale(LC_ALL, __sav);
! free(__sav);
return __ret;
}
#else
--- 1977,2007 ----
{
int __ret;
char* __old = setlocale(LC_ALL, NULL);
!
! // Only do all this expensive malloc/free, string copy and locale
! // setting if the locale is not already what we want.
! char* __sav;
! if (!(__old[0] == 'C' && __old[1] == '\0'))
! {
! __sav = static_cast<char*>(malloc(strlen(__old) + 1));
! if (__sav)
! strcpy(__sav, __old);
! setlocale(LC_ALL, "C");
! }
! else
! __sav = 0;
!
if (__prec >= 0)
__ret = snprintf(__out, __size, __fmt, __prec, __v);
else
__ret = snprintf(__out, __size, __fmt, __v);
!
! // Do we need to clean up?
! if(__sav)
! {
! setlocale(LC_ALL, __sav);
! free(__sav);
! }
return __ret;
}
#else
*************** namespace std
*** 1997,2012 ****
{
int __ret;
char* __old = setlocale(LC_ALL, NULL);
! char* __sav = static_cast<char*>(malloc(strlen(__old) + 1));
! if (__sav)
! strcpy(__sav, __old);
! setlocale(LC_ALL, "C");
if (__prec >= 0)
__ret = sprintf(__out, __fmt, __prec, __v);
else
__ret = sprintf(__out, __fmt, __v);
! setlocale(LC_ALL, __sav);
! free(__sav);
return __ret;
}
#endif
--- 2012,2042 ----
{
int __ret;
char* __old = setlocale(LC_ALL, NULL);
!
! // Only do all this expensive malloc/free, string copy and locale
! // setting if the locale is not already what we want.
! char* __sav;
! if (!(__old[0] == 'C' && __old[1] == '\0'))
! {
! __sav = static_cast<char*>(malloc(strlen(__old) + 1));
! if (__sav)
! strcpy(__sav, __old);
! setlocale(LC_ALL, "C");
! }
! else
! __sav = 0;
!
if (__prec >= 0)
__ret = sprintf(__out, __fmt, __prec, __v);
else
__ret = sprintf(__out, __fmt, __v);
!
! // Do we need to clean up?
! if(__sav)
! {
! setlocale(LC_ALL, __sav);
! free(__sav);
! }
return __ret;
}
#endif
More information about the Libstdc++
mailing list