This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
      }
  }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]