This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Fix libstdc++/13341 (speed-up <wchar_t>::do_narrow/widen)
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Thu, 11 Dec 2003 17:24:16 +0100
- Subject: [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;
+ }