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] Speed-up do_is(ctype_base::space, wchar_t)


Hi,

this is something I noticed while working on 22515: for wchar_t,
important istream functions (sentry, operator>>(string/CharT*), ws) are
spending *a lot* of time in ctype::do_is(mask, CharT) due to the
is(ctype_base::space, CharT) calls (*). As an example, reading back from
file ten millions of newline separated integers (from 0 to 9999999) via

  std::wifstream in("input_test");
  std::wstring j;

  for (int i = 0; i < 10000000; ++i)
    in >> j;
  return 0;

leads to a profile with do_is on top, with 34% of the total time!
Indeed, for each call, we are looping over all the possible elementary
bit masks with:

      for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
      if (__m & _M_bit[__bitcur]
          && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
        {
          __ret = true;
          break;
        }

which takes a lot of time (+ the cost of the virtual function call, not
present for plain char). But, on GNU systems (i.e., in the GNU locale
model) we *know* that the encoding of ctype_base::space is _M_bit[5] and
we can check first whether __m is exactly _M_bit[5].

For the example above, do_is drops to the third place with 14% of the
total time, which changes:

mainline
--
8.440u 0.090s 0:08.56 99.6%     0+0k 0+0io 213pf+0w

mainline + patch
---
6.600u 0.090s 0:06.71 99.7%     0+0k 0+0io 213pf+0w

Actually we already have in the performance testsuite a testcase which
exactly tracks this performance component, is_wchar_t.cc. The C++ case
changes:

mainline
--
2.930u 0.000s 0:02.93 100.0%    0+0k 0+0io 177pf+0w

mainline + patch
--
1.760u 0.000s 0:01.76 100.0%    0+0k 0+0io 177pf+0w

I'll keep on investigating this issue to see whether we can do something
more general within the current ABI but I'd like to commit first this
improvement.

Paolo.

(*) Actually, in our whole implementation ctype_base::space is the only
used mask, besides a single occurrence of ctype_base::upper in time_get.

////////////////
2005-07-18  Paolo Carlini  <pcarlini@suse.de>

	* config/locale/gnu/ctype_members.cc (do_is(mask, wchar_t)):
	Speed-up for the common case of mask == ctype_base::space.
Index: ctype_members.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/locale/gnu/ctype_members.cc,v
retrieving revision 1.19
diff -p -r1.19 ctype_members.cc
*** ctype_members.cc	12 Aug 2004 09:46:39 -0000	1.19
--- ctype_members.cc	17 Jul 2005 09:04:30 -0000
*************** namespace std
*** 134,150 ****
    ctype<wchar_t>::
    do_is(mask __m, wchar_t __c) const
    { 
!     // Highest bitmask in ctype_base == 10, but extra in "C"
!     // library for blank.
      bool __ret = false;
!     const size_t __bitmasksize = 11; 
!     for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
!       if (__m & _M_bit[__bitcur]
! 	  && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
! 	{
! 	  __ret = true;
! 	  break;
! 	}
      return __ret;    
    }
    
--- 134,160 ----
    ctype<wchar_t>::
    do_is(mask __m, wchar_t __c) const
    { 
!     // The case of __m == ctype_base::space is particularly important,
!     // due to its use in many istream functions.  Therefore we deal with
!     // it first, exploiting the knowledge that on GNU systems _M_bit[5]
!     // is the mask corresponding to ctype_base::space.  NB: an encoding
!     // change would not affect correctness!
      bool __ret = false;
!     if (__m == _M_bit[5])
!       __ret = __iswctype_l(__c, _M_wmask[5], _M_c_locale_ctype);
!     else
!       {
! 	// Highest bitmask in ctype_base == 10, but extra in "C"
! 	// library for blank.
! 	const size_t __bitmasksize = 11; 
! 	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
! 	  if (__m & _M_bit[__bitcur]
! 	      && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
! 	    {
! 	      __ret = true;
! 	      break;
! 	    }
!       }
      return __ret;    
    }
    

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