This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Tiny improvement for libstdc++/11602
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 18 Nov 2003 22:26:06 +0100
- Subject: [Patch] Tiny improvement for libstdc++/11602
Hi,
in order to really fix this performance problem drastic changes are
needed, most probably avoiding completely wcrtomb & co.
Anyway, the change below is really straighrforward and does a little
good. On my machine (P4-2400, -O2), for cspeed.cc, codecvt 100000:
3.4
---
15.590u 0.000s 0:15.87 98.2% 0+0k 0+0io 228pf+0w
3.4 + patch below
-----------------
9.600u 0.000s 0:09.76 98.3% 0+0k 0+0io 187pf+0w
Regression tested x86-linux. Barring objections, will commit soon.
Paolo.
//////////
2003-11-18 Paolo Carlini <pcarlini@suse.de>
* config/locale/gnu/codecvt_members.cc (do_out): If
we can upper bound the total number of external chars
to something smaller than __to_end - __to avoid the
temporary buffer, the memcopy and simplify the loop.
diff -prN libstdc++-v3-orig/config/locale/gnu/codecvt_members.cc libstdc++-v3/config/locale/gnu/codecvt_members.cc
*** libstdc++-v3-orig/config/locale/gnu/codecvt_members.cc Sat Jul 5 06:05:30 2003
--- libstdc++-v3/config/locale/gnu/codecvt_members.cc Tue Nov 18 22:06:45 2003
*************** namespace std
*** 48,60 ****
extern_type*& __to_next) const
{
result __ret = ok;
- // The conversion must be done using a temporary destination buffer
- // since it is not possible to pass the size of the buffer to wcrtomb
- extern_type __buf[MB_LEN_MAX];
// A temporary state must be used since the result of the last
// conversion may be thrown away.
! state_type __tmp_state(__state);
!
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_codecvt);
#endif
--- 48,57 ----
extern_type*& __to_next) const
{
result __ret = ok;
// A temporary state must be used since the result of the last
// conversion may be thrown away.
! state_type __tmp_state(__state);
!
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_codecvt);
#endif
*************** namespace std
*** 62,85 ****
// The conversion must be done by calling wcrtomb in a loop rather
// than using wcsrtombs because wcsrtombs assumes that the input is
// zero-terminated.
! while (__from < __from_end && __to < __to_end)
{
! size_t __conv = wcrtomb(__buf, *__from, &__tmp_state);
! if (__conv == static_cast<size_t>(-1))
{
! __ret = error;
! break;
}
- else if (__conv > static_cast<size_t>(__to_end - __to))
- {
- __ret = partial;
- break;
- }
-
- memcpy(__to, __buf, __conv);
- __state = __tmp_state;
- __to += __conv;
- __from++;
}
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
--- 59,104 ----
// The conversion must be done by calling wcrtomb in a loop rather
// than using wcsrtombs because wcsrtombs assumes that the input is
// zero-terminated.
!
! // Either we can upper bound the total number of external characters to
! // something smaller than __to_end - __to or the conversion must be done
! // using a temporary destination buffer since it is not possible to
! // pass the size of the buffer to wcrtomb
! if (MB_CUR_MAX * (__from_end - __from) <= __to_end - __to)
! while (__from < __from_end)
! {
! const size_t __conv = wcrtomb(__to, *__from, &__tmp_state);
! if (__conv == static_cast<size_t>(-1))
! {
! __ret = error;
! break;
! }
! __state = __tmp_state;
! __to += __conv;
! __from++;
! }
! else
{
! extern_type __buf[MB_LEN_MAX];
! while (__from < __from_end && __to < __to_end)
{
! const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state);
! if (__conv == static_cast<size_t>(-1))
! {
! __ret = error;
! break;
! }
! else if (__conv > static_cast<size_t>(__to_end - __to))
! {
! __ret = partial;
! break;
! }
!
! memcpy(__to, __buf, __conv);
! __state = __tmp_state;
! __to += __conv;
! __from++;
}
}
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)