This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] libstdc++/19642
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Sat, 29 Jan 2005 10:40:59 +0100
- Subject: [Patch] libstdc++/19642
Hi,
on targets using the generic locale model, setlocale can be very slow, thud
the performance of __convert_from_v simply *awful* (~50x sprintf).
The below simple tweak avoids the most costly setlocale calls (*, != NULL)
in the common case ("C" locale) and also uses the cheaper LC_NUMERIC
instead of the full LC_ALL, not needed for sprintf. As the number provided
by submitter show, it's *very* effective for its semplicity. During the past
days I checked the basic assumptions on a very wide range of different
targets
(many thanks to all the people that helped!), and I'd like to commit it to
mainline, possibly 3_4 too if testing goes well.
Regtested x86/ia64-linux (in the generic model, of course).
Paolo.
/////////////////
2005-01-30 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/19642
* config/locale/generic/c_locale.h (__convert_from_v): Switch only
LC_NUMERIC, and only when actually != "C".
diff -prN libstdc++-v3-orig/config/locale/generic/c_locale.h libstdc++-v3/config/locale/generic/c_locale.h
*** libstdc++-v3-orig/config/locale/generic/c_locale.h Mon Aug 16 16:42:38 2004
--- libstdc++-v3/config/locale/generic/c_locale.h Thu Jan 27 14:54:17 2005
*************** namespace std
*** 59,76 ****
const char* __fmt,
_Tv __v, const __c_locale&, int __prec)
{
! char* __old = std::setlocale(LC_ALL, NULL);
! char* __sav = new char[std::strlen(__old) + 1];
! std::strcpy(__sav, __old);
! std::setlocale(LC_ALL, "C");
#ifdef _GLIBCXX_USE_C99
const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
#else
const int __ret = std::sprintf(__out, __fmt, __prec, __v);
#endif
! std::setlocale(LC_ALL, __sav);
! delete [] __sav;
return __ret;
}
}
--- 59,84 ----
const char* __fmt,
_Tv __v, const __c_locale&, int __prec)
{
! char* __old = std::setlocale(LC_NUMERIC, NULL);
! char* __sav = NULL;
! if (std::strcmp(__old, "C"))
! {
! __sav = new char[std::strlen(__old) + 1];
! std::strcpy(__sav, __old);
! std::setlocale(LC_NUMERIC, "C");
! }
#ifdef _GLIBCXX_USE_C99
const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
#else
const int __ret = std::sprintf(__out, __fmt, __prec, __v);
#endif
!
! if (__sav)
! {
! std::setlocale(LC_NUMERIC, __sav);
! delete [] __sav;
! }
return __ret;
}
}