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>
|
2003-12-16 Jerry Quinn <jlquinn@optonline.net>
|
||||||
|
|
||||||
* include/bits/locale_facets.h (widen, narrow): Uncomment the
|
* 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.
|
// encoding of the various categories in /usr/include/ctype.h.
|
||||||
const size_t __bitmasksize = 15;
|
const size_t __bitmasksize = 15;
|
||||||
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
||||||
{
|
if (__m & _M_bit[__bitcur]
|
||||||
const mask __bit = static_cast<mask>(1 << __bitcur);
|
&& iswctype(__c, _M_wmask[__bitcur]))
|
||||||
if (__m & __bit)
|
{
|
||||||
__ret |= iswctype(__c, _M_convert_to_wmask(__bit));
|
__ret = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
return __ret;
|
return __ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,11 +155,8 @@ namespace std
|
|||||||
const size_t __bitmasksize = 15;
|
const size_t __bitmasksize = 15;
|
||||||
mask __m = 0;
|
mask __m = 0;
|
||||||
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
||||||
{
|
if (iswctype(*__lo, _M_wmask[__bitcur]))
|
||||||
const mask __bit = static_cast<mask>(1 << __bitcur);
|
__m |= _M_bit[__bitcur];
|
||||||
if (iswctype(*__lo, _M_convert_to_wmask(__bit)))
|
|
||||||
__m |= __bit;
|
|
||||||
}
|
|
||||||
*__vec = __m;
|
*__vec = __m;
|
||||||
}
|
}
|
||||||
return __hi;
|
return __hi;
|
||||||
@ -258,6 +256,12 @@ namespace std
|
|||||||
for (size_t __i = 0;
|
for (size_t __i = 0;
|
||||||
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
|
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
|
||||||
_M_widen[__i] = btowc(__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
|
#endif // _GLIBCXX_USE_WCHAR_T
|
||||||
}
|
}
|
||||||
|
@ -139,12 +139,12 @@ namespace std
|
|||||||
bool __ret = false;
|
bool __ret = false;
|
||||||
const size_t __bitmasksize = 11;
|
const size_t __bitmasksize = 11;
|
||||||
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
||||||
{
|
if (__m & _M_bit[__bitcur]
|
||||||
const mask __bit = static_cast<mask>(_ISbit(__bitcur));
|
&& __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
|
||||||
if (__m & __bit)
|
{
|
||||||
__ret |= __iswctype_l(__c, _M_convert_to_wmask(__bit),
|
__ret = true;
|
||||||
_M_c_locale_ctype);
|
break;
|
||||||
}
|
}
|
||||||
return __ret;
|
return __ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,19 +152,15 @@ namespace std
|
|||||||
ctype<wchar_t>::
|
ctype<wchar_t>::
|
||||||
do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
|
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"
|
// Highest bitmask in ctype_base == 10, but extra in "C"
|
||||||
// library for blank.
|
// library for blank.
|
||||||
const size_t __bitmasksize = 11;
|
const size_t __bitmasksize = 11;
|
||||||
mask __m = 0;
|
mask __m = 0;
|
||||||
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
|
||||||
{
|
if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
|
||||||
const mask __bit = static_cast<mask>(_ISbit(__bitcur));
|
__m |= _M_bit[__bitcur];
|
||||||
if (__iswctype_l(*__lo, _M_convert_to_wmask(__bit),
|
|
||||||
_M_c_locale_ctype))
|
|
||||||
__m |= __bit;
|
|
||||||
}
|
|
||||||
*__vec = __m;
|
*__vec = __m;
|
||||||
}
|
}
|
||||||
return __hi;
|
return __hi;
|
||||||
@ -279,6 +275,12 @@ namespace std
|
|||||||
for (size_t __i = 0;
|
for (size_t __i = 0;
|
||||||
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
|
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
|
||||||
_M_widen[__i] = btowc(__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)
|
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
|
||||||
__uselocale(__old);
|
__uselocale(__old);
|
||||||
#endif
|
#endif
|
||||||
|
@ -247,7 +247,7 @@ namespace std
|
|||||||
|
|
||||||
virtual const char_type*
|
virtual const char_type*
|
||||||
do_narrow(const char_type* __lo, const char_type* __hi,
|
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.
|
// NB: Generic, mostly useless implementation.
|
||||||
@ -394,16 +394,16 @@ namespace std
|
|||||||
narrow(char_type __c, char __dfault) const
|
narrow(char_type __c, char __dfault) const
|
||||||
{
|
{
|
||||||
if (_M_narrow[__c]) return _M_narrow[__c];
|
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;
|
if (__t != __dfault) _M_narrow[__c] = __t;
|
||||||
return __t;
|
return __t;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char_type*
|
const char_type*
|
||||||
narrow(const char_type* __lo, const char_type* __hi,
|
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);
|
memcpy(__to, __lo, __hi - __lo);
|
||||||
return __hi;
|
return __hi;
|
||||||
@ -464,13 +464,13 @@ namespace std
|
|||||||
void _M_widen_init() const
|
void _M_widen_init() const
|
||||||
{
|
{
|
||||||
char __tmp[sizeof(_M_widen)];
|
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;
|
__tmp[__i] = __i;
|
||||||
do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
|
do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
|
||||||
|
|
||||||
_M_widen_ok = 1;
|
_M_widen_ok = 1;
|
||||||
// Set _M_widen_ok to 2 if memcpy can't be used.
|
// 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])
|
if (__tmp[__i] != _M_widen[__i])
|
||||||
{
|
{
|
||||||
_M_widen_ok = 2;
|
_M_widen_ok = 2;
|
||||||
@ -484,26 +484,24 @@ namespace std
|
|||||||
void _M_narrow_init() const
|
void _M_narrow_init() const
|
||||||
{
|
{
|
||||||
char __tmp[sizeof(_M_narrow)];
|
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;
|
__tmp[__i] = __i;
|
||||||
do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
|
do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
|
||||||
|
|
||||||
// Check if any default values were created. Do this by
|
// Check if any default values were created. Do this by
|
||||||
// renarrowing with a different default value and comparing.
|
// renarrowing with a different default value and comparing.
|
||||||
bool __consecutive = true;
|
bool __consecutive = true;
|
||||||
for (unsigned __i = 0; __i < sizeof(_M_narrow); ++__i)
|
for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
|
||||||
{
|
if (!_M_narrow[__i])
|
||||||
char __c[1];
|
{
|
||||||
if (!_M_narrow[__i])
|
char __c;
|
||||||
{
|
do_narrow(__tmp + __i, __tmp + __i + 1, 1, &__c);
|
||||||
do_narrow(__tmp + __i, __tmp + __i + 1, 1, __c);
|
if (__c == 1)
|
||||||
if (__c[0] == 1)
|
{
|
||||||
{
|
__consecutive = false;
|
||||||
__consecutive = false;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
_M_narrow_ok = __consecutive ? 1 : 2;
|
_M_narrow_ok = __consecutive ? 1 : 2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -530,6 +528,10 @@ namespace std
|
|||||||
char _M_narrow[128];
|
char _M_narrow[128];
|
||||||
wint_t _M_widen[1 + static_cast<unsigned char>(-1)];
|
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:
|
public:
|
||||||
// Data Members:
|
// Data Members:
|
||||||
static locale::id id;
|
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;
|
resource_counter resource;
|
||||||
const long iters = 200000000;
|
const long iters = 200000000;
|
||||||
char bufin[] = "This was an attempt to bypass string construction just for test.";
|
char bufin[] = "This was an attempt to bypass string construction just for test.";
|
||||||
char bufout[sizeof(bufin) + 1];
|
char bufout[sizeof(bufin)];
|
||||||
|
|
||||||
locale loc;
|
locale loc;
|
||||||
const ctype<char>& ct = use_facet<ctype<char> >(loc);
|
const ctype<char>& ct = use_facet<ctype<char> >(loc);
|
||||||
|
@ -35,7 +35,7 @@ int main()
|
|||||||
|
|
||||||
time_counter time;
|
time_counter time;
|
||||||
resource_counter resource;
|
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)];
|
char bufc[sizeof(bufwc) / sizeof(wchar_t)];
|
||||||
|
|
||||||
locale loc;
|
locale loc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user