re PR libstdc++/11723 (ctype<wchar_t>::do_is(mask, wchar_t) is slow)

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

	PR libstdc++/11723
	* include/bits/locale_facets.h: Add _M_bit and _M_wmask,
	used to speed up the computation of ctype::do_is.
	* config/locale/generic/ctype_members.cc
	(_M_initialize_ctype): Fill _M_bit and _M_wmask.
	(ctype::do_is): Use _M_bit and _M_wmask.
	* config/locale/gnu/ctype_members.cc: Likewise.
	* testsuite/performance/is_wchar_t.cc: New.

	* testsuite/performance/narrow_widen_wchar_t.cc: Tweak
	string literal (incorrect citation ;)

	* include/bits/locale_facets.h: Minor tweaks, const
	correctness, unsigned -> size_t.

From-SVN: r74686
This commit is contained in:
Paolo Carlini 2003-12-16 11:00:52 +00:00 committed by Paolo Carlini
parent a0c6873702
commit 9a1349b920
7 changed files with 157 additions and 45 deletions

View File

@ -1,3 +1,20 @@
2003-12-16 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/11723
* include/bits/locale_facets.h: Add _M_bit and _M_wmask,
used to speed up the computation of ctype::do_is.
* config/locale/generic/ctype_members.cc
(_M_initialize_ctype): Fill _M_bit and _M_wmask.
(ctype::do_is): Use _M_bit and _M_wmask.
* config/locale/gnu/ctype_members.cc: Likewise.
* testsuite/performance/is_wchar_t.cc: New.
* testsuite/performance/narrow_widen_wchar_t.cc: Tweak
string literal (incorrect citation ;)
* include/bits/locale_facets.h: Minor tweaks, const
correctness, unsigned -> size_t.
2003-12-16 Jerry Quinn <jlquinn@optonline.net>
* include/bits/locale_facets.h (widen, narrow): Uncomment the

View File

@ -135,11 +135,12 @@ namespace std
// encoding of the various categories in /usr/include/ctype.h.
const size_t __bitmasksize = 15;
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
{
const mask __bit = static_cast<mask>(1 << __bitcur);
if (__m & __bit)
__ret |= iswctype(__c, _M_convert_to_wmask(__bit));
}
if (__m & _M_bit[__bitcur]
&& iswctype(__c, _M_wmask[__bitcur]))
{
__ret = true;
break;
}
return __ret;
}
@ -154,11 +155,8 @@ namespace std
const size_t __bitmasksize = 15;
mask __m = 0;
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
{
const mask __bit = static_cast<mask>(1 << __bitcur);
if (iswctype(*__lo, _M_convert_to_wmask(__bit)))
__m |= __bit;
}
if (iswctype(*__lo, _M_wmask[__bitcur]))
__m |= _M_bit[__bitcur];
*__vec = __m;
}
return __hi;
@ -258,6 +256,12 @@ namespace std
for (size_t __i = 0;
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
_M_widen[__i] = btowc(__i);
for (size_t __i = 0; __i <= 15; ++__i)
{
_M_bit[__i] = static_cast<mask>(1 << __i);
_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
}
}
#endif // _GLIBCXX_USE_WCHAR_T
}

View File

@ -139,12 +139,12 @@ namespace std
bool __ret = false;
const size_t __bitmasksize = 11;
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
{
const mask __bit = static_cast<mask>(_ISbit(__bitcur));
if (__m & __bit)
__ret |= __iswctype_l(__c, _M_convert_to_wmask(__bit),
_M_c_locale_ctype);
}
if (__m & _M_bit[__bitcur]
&& __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
{
__ret = true;
break;
}
return __ret;
}
@ -152,19 +152,15 @@ namespace std
ctype<wchar_t>::
do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
{
for (;__lo < __hi; ++__vec, ++__lo)
for (; __lo < __hi; ++__vec, ++__lo)
{
// Highest bitmask in ctype_base == 10, but extra in "C"
// library for blank.
const size_t __bitmasksize = 11;
mask __m = 0;
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
{
const mask __bit = static_cast<mask>(_ISbit(__bitcur));
if (__iswctype_l(*__lo, _M_convert_to_wmask(__bit),
_M_c_locale_ctype))
__m |= __bit;
}
if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
__m |= _M_bit[__bitcur];
*__vec = __m;
}
return __hi;
@ -279,6 +275,12 @@ namespace std
for (size_t __i = 0;
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
_M_widen[__i] = btowc(__i);
for (size_t __i = 0; __i <= 11; ++__i)
{
_M_bit[__i] = static_cast<mask>(_ISbit(__i));
_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
}
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__uselocale(__old);
#endif

View File

@ -247,7 +247,7 @@ namespace std
virtual const char_type*
do_narrow(const char_type* __lo, const char_type* __hi,
char __dfault, char* __dest) const = 0;
char __dfault, char* __dest) const = 0;
};
// NB: Generic, mostly useless implementation.
@ -394,16 +394,16 @@ namespace std
narrow(char_type __c, char __dfault) const
{
if (_M_narrow[__c]) return _M_narrow[__c];
char __t = do_narrow(__c, __dfault);
const char __t = do_narrow(__c, __dfault);
if (__t != __dfault) _M_narrow[__c] = __t;
return __t;
}
const char_type*
narrow(const char_type* __lo, const char_type* __hi,
char __dfault, char *__to) const
char __dfault, char *__to) const
{
if (__builtin_expect(_M_narrow_ok==1,true))
if (__builtin_expect(_M_narrow_ok == 1,true))
{
memcpy(__to, __lo, __hi - __lo);
return __hi;
@ -464,13 +464,13 @@ namespace std
void _M_widen_init() const
{
char __tmp[sizeof(_M_widen)];
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
__tmp[__i] = __i;
do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
_M_widen_ok = 1;
// Set _M_widen_ok to 2 if memcpy can't be used.
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
if (__tmp[__i] != _M_widen[__i])
{
_M_widen_ok = 2;
@ -484,26 +484,24 @@ namespace std
void _M_narrow_init() const
{
char __tmp[sizeof(_M_narrow)];
for (unsigned __i = 0; __i < sizeof(_M_narrow); ++__i)
for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
__tmp[__i] = __i;
do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
// Check if any default values were created. Do this by
// renarrowing with a different default value and comparing.
bool __consecutive = true;
for (unsigned __i = 0; __i < sizeof(_M_narrow); ++__i)
{
char __c[1];
if (!_M_narrow[__i])
{
do_narrow(__tmp + __i, __tmp + __i + 1, 1, __c);
if (__c[0] == 1)
{
__consecutive = false;
break;
}
}
}
for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
if (!_M_narrow[__i])
{
char __c;
do_narrow(__tmp + __i, __tmp + __i + 1, 1, &__c);
if (__c == 1)
{
__consecutive = false;
break;
}
}
_M_narrow_ok = __consecutive ? 1 : 2;
}
};
@ -530,6 +528,10 @@ namespace std
char _M_narrow[128];
wint_t _M_widen[1 + static_cast<unsigned char>(-1)];
// Pre-computed elements for do_is.
mask _M_bit[16];
__wmask_type _M_wmask[16];
public:
// Data Members:
static locale::id id;

View File

@ -0,0 +1,87 @@
// 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 <cwctype>
#include <cstddef>
#include <testsuite_performance.h>
int main()
{
using namespace std;
using namespace __gnu_test;
time_counter time;
resource_counter resource;
const wchar_t str[] =
L"Is this the real life?\n"
L"Is this just fantasy?\n"
L"Caught in a landslide\n"
L"No escape from reality\n"
L"Open your eyes\n"
L"Look up to the skies and see\n"
L"I'm just a poor boy\n"
L"I need no sympathy\n"
L"Because I'm easy come, easy go\n"
L"Little high, little low"
L"Anyway the wind blows\n"
L"Doesn't really matter to me\n"
L"To me\n"
L" -- Queen\n";
const size_t len = sizeof(str) / sizeof(str[0]) - 1;
locale loc;
const ctype<wchar_t>& ct = use_facet<ctype<wchar_t> >(loc);
// C
wctype_t w = wctype("space");
start_counters(time, resource);
for (int j = 0; j < 200000; ++j)
{
for (size_t i = 0; i < len; ++i)
{
iswctype(str[i], w);
}
}
stop_counters(time, resource);
report_performance(__FILE__, "C", time, resource);
clear_counters(time, resource);
// C++
start_counters(time, resource);
for (int j = 0; j < 200000; ++j)
{
for (size_t i = 0; i < len; ++i)
{
ct.is(ctype_base::space, str[i]);
}
}
stop_counters(time, resource);
report_performance(__FILE__, "C++", time, resource);
return 0;
}

View File

@ -37,7 +37,7 @@ int main()
resource_counter resource;
const long iters = 200000000;
char bufin[] = "This was an attempt to bypass string construction just for test.";
char bufout[sizeof(bufin) + 1];
char bufout[sizeof(bufin)];
locale loc;
const ctype<char>& ct = use_facet<ctype<char> >(loc);

View File

@ -35,7 +35,7 @@ int main()
time_counter time;
resource_counter resource;
wchar_t bufwc[] = L"M'innamoravo di tutto (Fabrizio De Andre')";
wchar_t bufwc[] = L"Mi innamoravo di tutto (Fabrizio De Andre')";
char bufc[sizeof(bufwc) / sizeof(wchar_t)];
locale loc;