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] Fix libstdc++/13341 (speed-up <wchar_t>::do_narrow/widen)


Hi,

this is my modest proposal, limited to the wchar_t versions of
do_widen and do_narrow. For the common case it results in a
pretty good speed up:

for (long i = 0; i < 100000000; ++i)
  ct.widen(i % 128);
  // ct.narrow(i % 128, '*');

On my P4-2400, -O2:

3.4
---
widen:   7.650u 0.000s 0:07.66 99.8%     0+0k 0+0io 167pf+0w
narrow: 11.650u 0.000s 0:11.69 99.6%     0+0k 0+0io 168pf+0w

3.4 + patch
-----------
widen:   1.270u 0.010s 0:01.28 100.0%    0+0k 0+0io 169pf+0w
narrow:  1.270u 0.000s 0:01.27 100.0%    0+0k 0+0io 169pf+0w


Tested x86-linux (gnu/generic).


I will wait some 24 hours for comments...

Paolo.

///////////////
2003-12-11  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/13341
	* include/bits/locale_facets.h (ctype<wchar_t>): Declare
	_M_initialize_ctype and define _M_narrow and _M_widen.
	* src/ctype.cc (ctype<wchar_t>::ctype(size_t),
	ctype<wchar_t>::ctype(__c_locale, size_t)): Call 
	_M_initialize_ctype to fill _M_narrow and _M_widen.
	* config/locale/generic/ctype_members.cc (do_narrow, do_widen)
	Use _M_narrow and _M_widen when possible, instead of calling
	wctob and btowc, respectively.
	(_M_initialize_ctype): Define, it fills at construction time
	_M_narrow and _M_widen.
	* config/locale/gnu/ctype_members.cc: Likewise.
	* testsuite/performance/narrow_widen_wchar_t.cc: New.
diff -prN libstdc++-v3-orig/config/locale/generic/ctype_members.cc libstdc++-v3/config/locale/generic/ctype_members.cc
*** libstdc++-v3-orig/config/locale/generic/ctype_members.cc	Wed Oct 22 20:58:30 2003
--- libstdc++-v3/config/locale/generic/ctype_members.cc	Thu Dec 11 14:29:57 2003
*************** namespace std
*** 185,191 ****
    wchar_t
    ctype<wchar_t>::
    do_widen(char __c) const
!   { return btowc(static_cast<unsigned char>(__c)); }
    
    const char* 
    ctype<wchar_t>::
--- 185,199 ----
    wchar_t
    ctype<wchar_t>::
    do_widen(char __c) const
!   { 
!     wchar_t __ret;
!     const unsigned char __uc = static_cast<unsigned char>(__c);
!     if (__uc < 128)
!       __ret = _M_widen[__uc];
!     else
!       __ret = btowc(__uc);
!     return __ret;
!   }
    
    const char* 
    ctype<wchar_t>::
*************** namespace std
*** 193,199 ****
    {
      while (__lo < __hi)
        {
! 	*__dest = btowc(static_cast<unsigned char>(*__lo));
  	++__lo;
  	++__dest;
        }
--- 201,211 ----
    {
      while (__lo < __hi)
        {
! 	const unsigned char __uc = static_cast<unsigned char>(*__lo);	
! 	if (__uc < 128)
! 	  *__dest = _M_widen[__uc];
! 	else
! 	  *__dest = btowc(__uc);	
  	++__lo;
  	++__dest;
        }
*************** namespace std
*** 204,210 ****
    ctype<wchar_t>::
    do_narrow(wchar_t __wc, char __dfault) const
    { 
!     int __c = wctob(__wc);
      return (__c == EOF ? __dfault : static_cast<char>(__c)); 
    }
  
--- 216,226 ----
    ctype<wchar_t>::
    do_narrow(wchar_t __wc, char __dfault) const
    { 
!     int __c;
!     if (__wc >= 0 && __wc < 128)
!       __c = _M_narrow[__wc];
!     else
!       __c = wctob(__wc);
      return (__c == EOF ? __dfault : static_cast<char>(__c)); 
    }
  
*************** namespace std
*** 215,226 ****
    {
      while (__lo < __hi)
        {
! 	int __c = wctob(*__lo);
  	*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
  	++__lo;
  	++__dest;
        }
      return __hi;
    }
  #endif //  _GLIBCXX_USE_WCHAR_T
  }
--- 231,255 ----
    {
      while (__lo < __hi)
        {
! 	int __c;
! 	if (*__lo >= 0 && *__lo < 128)
! 	  __c = _M_narrow[*__lo];
! 	else
! 	  __c = wctob(*__lo);
  	*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
  	++__lo;
  	++__dest;
        }
      return __hi;
    }
+ 
+   void
+   ctype<wchar_t>::_M_initialize_ctype()
+   {
+     for (wint_t __i = 0; __i < 128; ++__i)
+       _M_narrow[__i] =  wctob(__i);
+     for (int __i = 0; __i < 128; ++__i)
+       _M_widen[__i] =  btowc(__i);
+   }
  #endif //  _GLIBCXX_USE_WCHAR_T
  }
diff -prN libstdc++-v3-orig/config/locale/gnu/ctype_members.cc libstdc++-v3/config/locale/gnu/ctype_members.cc
*** libstdc++-v3-orig/config/locale/gnu/ctype_members.cc	Wed Oct 22 20:58:30 2003
--- libstdc++-v3/config/locale/gnu/ctype_members.cc	Thu Dec 11 14:25:43 2003
*************** namespace std
*** 192,204 ****
    ctype<wchar_t>::
    do_widen(char __c) const
    {
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
!     __c_locale __old = __uselocale(_M_c_locale_ctype);
  #endif
!     wchar_t __ret = btowc(static_cast<unsigned char>(__c));
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
!     __uselocale(__old);
  #endif
      return __ret;
    }
  
--- 192,211 ----
    ctype<wchar_t>::
    do_widen(char __c) const
    {
+     wchar_t __ret;
+     const unsigned char __uc = static_cast<unsigned char>(__c);
+     if (__uc < 128)
+       __ret = _M_widen[__uc];
+     else
+       {
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
! 	__c_locale __old = __uselocale(_M_c_locale_ctype);
  #endif
! 	__ret = btowc(__uc);
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
! 	__uselocale(__old);
  #endif
+       }
      return __ret;
    }
  
*************** namespace std
*** 211,217 ****
  #endif
      while (__lo < __hi)
        {
! 	*__dest = btowc(static_cast<unsigned char>(*__lo));
  	++__lo;
  	++__dest;
        }
--- 218,228 ----
  #endif
      while (__lo < __hi)
        {
! 	const unsigned char __uc = static_cast<unsigned char>(*__lo);	
! 	if (__uc < 128)
! 	  *__dest = _M_widen[__uc];
! 	else
! 	  *__dest = btowc(__uc);	
  	++__lo;
  	++__dest;
        }
*************** namespace std
*** 225,237 ****
    ctype<wchar_t>::
    do_narrow(wchar_t __wc, char __dfault) const
    { 
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
!     __c_locale __old = __uselocale(_M_c_locale_ctype);
  #endif
!     int __c = wctob(__wc);
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
!     __uselocale(__old);
  #endif
      return (__c == EOF ? __dfault : static_cast<char>(__c)); 
    }
  
--- 236,254 ----
    ctype<wchar_t>::
    do_narrow(wchar_t __wc, char __dfault) const
    { 
+     int __c;
+     if (__wc >= 0 && __wc < 128)
+       __c = _M_narrow[__wc];
+     else
+       {
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
! 	__c_locale __old = __uselocale(_M_c_locale_ctype);
  #endif
! 	__c = wctob(__wc);
  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
! 	__uselocale(__old);
  #endif
+       }
      return (__c == EOF ? __dfault : static_cast<char>(__c)); 
    }
  
*************** namespace std
*** 245,251 ****
  #endif
      while (__lo < __hi)
        {
! 	int __c = wctob(*__lo);
  	*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
  	++__lo;
  	++__dest;
--- 262,272 ----
  #endif
      while (__lo < __hi)
        {
! 	int __c;
! 	if (*__lo >= 0 && *__lo < 128)
! 	  __c = _M_narrow[*__lo];
! 	else
! 	  __c = wctob(*__lo);
  	*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
  	++__lo;
  	++__dest;
*************** namespace std
*** 255,259 ****
--- 276,295 ----
  #endif
      return __hi;
    }
+ 
+   void
+   ctype<wchar_t>::_M_initialize_ctype()
+   {
+ #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+     __c_locale __old = __uselocale(_M_c_locale_ctype);
+ #endif
+     for (wint_t __i = 0; __i < 128; ++__i)
+       _M_narrow[__i] =  wctob(__i);
+     for (int __i = 0; __i < 128; ++__i)
+       _M_widen[__i] =  btowc(__i);
+ #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+     __uselocale(__old);
+ #endif
+   }
  #endif //  _GLIBCXX_USE_WCHAR_T
  }
diff -prN libstdc++-v3-orig/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
*** libstdc++-v3-orig/include/bits/locale_facets.h	Mon Dec  8 16:37:02 2003
--- libstdc++-v3/include/bits/locale_facets.h	Thu Dec 11 14:05:37 2003
*************** namespace std
*** 446,451 ****
--- 446,455 ----
      protected:
        __c_locale		_M_c_locale_ctype;
  
+       // Pre-computed narrowed and widened chars in the range 0-127.
+       int                       _M_narrow[128];
+       wint_t                    _M_widen[128];
+ 
      public:
        // Data Members:
        static locale::id        	id;
*************** namespace std
*** 500,505 ****
--- 504,513 ----
        virtual const char_type*
        do_narrow(const char_type* __lo, const char_type* __hi,
  		char __dfault, char* __dest) const;
+ 
+       // For use at construction time only.
+       void 
+       _M_initialize_ctype();
      };
  
    template<>
diff -prN libstdc++-v3-orig/src/ctype.cc libstdc++-v3/src/ctype.cc
*** libstdc++-v3-orig/src/ctype.cc	Wed Oct 22 20:58:31 2003
--- libstdc++-v3/src/ctype.cc	Thu Dec 11 14:00:42 2003
*************** namespace std 
*** 87,97 ****
  #ifdef _GLIBCXX_USE_WCHAR_T
    ctype<wchar_t>::ctype(size_t __refs) 
    : __ctype_abstract_base<wchar_t>(__refs)
!   { _M_c_locale_ctype = _S_get_c_locale(); }
  
    ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs) 
    : __ctype_abstract_base<wchar_t>(__refs) 
!   { _M_c_locale_ctype = _S_clone_c_locale(__cloc); }
  
    ctype<wchar_t>::~ctype() 
    { _S_destroy_c_locale(_M_c_locale_ctype); }
--- 87,103 ----
  #ifdef _GLIBCXX_USE_WCHAR_T
    ctype<wchar_t>::ctype(size_t __refs) 
    : __ctype_abstract_base<wchar_t>(__refs)
!   { 
!     _M_c_locale_ctype = _S_get_c_locale();
!     _M_initialize_ctype();
!   }
  
    ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs) 
    : __ctype_abstract_base<wchar_t>(__refs) 
!   {
!     _M_c_locale_ctype = _S_clone_c_locale(__cloc);
!     _M_initialize_ctype();
!   }
  
    ctype<wchar_t>::~ctype() 
    { _S_destroy_c_locale(_M_c_locale_ctype); }
diff -prN libstdc++-v3-orig/testsuite/performance/narrow_widen_wchar_t.cc libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc
*** libstdc++-v3-orig/testsuite/performance/narrow_widen_wchar_t.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc	Thu Dec 11 16:27:12 2003
***************
*** 0 ****
--- 1,59 ----
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction.  Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License.  This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+ 
+ #include <locale>
+ #include <testsuite_performance.h>
+ 
+ int main()
+ {
+   using namespace std;
+   using namespace __gnu_test;
+ 
+   time_counter time;
+   resource_counter resource;
+   const long iters = 200000000;
+ 
+   locale loc;
+   const ctype<wchar_t>& ct = use_facet<ctype<wchar_t> >(loc);
+ 
+   // narrow
+   start_counters(time, resource);
+   for (long i = 0; i < iters; ++i)
+     ct.narrow(i % 128, '*');
+   stop_counters(time, resource);
+   report_performance(__FILE__, "narrow", time, resource);
+   clear_counters(time, resource);
+ 
+   // widen
+   start_counters(time, resource);
+   for (long i = 0; i < iters; ++i)
+     ct.widen(i % 128);
+   stop_counters(time, resource);
+   report_performance(__FILE__, "widen", time, resource);
+ 
+   return 0;
+ }

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