mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-30 07:14:09 +08:00
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:
parent
a0c6873702
commit
9a1349b920
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
87
libstdc++-v3/testsuite/performance/is_wchar_t.cc
Normal file
87
libstdc++-v3/testsuite/performance/is_wchar_t.cc
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user