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] Assign(_str, _pos, _n) (take2) + benchmarks


Hi again,
the first attempt turned out to have a stupid mistake affecting the performance:
the unnecessary use of resize. This is the next attempt, much simpler indeed:

//-----------

  basic_string&
  assign(const basic_string& __str, size_type __pos, size_type __n)
  {
    if (__pos > __str.size())
      __throw_out_of_range("basic_string::assign");
    if (_M_rep()->_M_is_shared() || _M_rep() != __str._M_rep())
      return _M_replace_safe(_M_ibegin(), _M_iend(),
                             __str._M_check(__pos),
                             __str._M_fold(__pos, __n));
    else
      {
        // Work in-place.
        bool __testn = __n < __str.size() - __pos;
        const size_type __newsize = __testn ? __n : __str.size() - __pos;
        // Avoid memmove, if possible.
        if (__pos >= __newsize)
          traits_type::copy(_M_data(), __str._M_data() + __pos, __newsize);
        else
          traits_type::move(_M_data(), __str._M_data() + __pos, __newsize);
        _M_rep()->_M_length = __newsize;
        return *this;
      }
  }

//-----------

These are the performance for the three different operating modes (-O2,
PII-400), I think they are pretty good :-)

//
//"self assign"

#include <string>
int main()
{
  std::string one;

  for (int i = 0; i < 2000000; ++i)
    {
      one = "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890";
      one.assign(one, 19, 80);
      one.assign(one, 9, 60);
      one.assign(one, 39, 10);
      one.assign(one, 0, 10);
    }
}

mainline + this patch
---------------------
7.100u 0.010s 0:07.21 98.6%     0+0k 0+0io 202pf+0w

2.95.3
------
7.510u 0.010s 0:07.62 98.6%     0+0k 0+0io 93pf+0w

mainline
--------
12.670u 0.010s 0:12.87 98.5%    0+0k 0+0io 201pf+0w

//
//
//----------------
// "shared assign"

#include <string>
int main()
{
  std::string one, two;

  for (int i = 0; i < 2000000; ++i)
    {
      one = "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890";
      two = one;
      two.assign(one, 19, 80);
      two.assign(one, 9, 60);
      two.assign(one, 39, 10);
      two.assign(one, 0, 10);
    }
}

mainline + this patch
---------------------
8.910u 0.030s 0:09.06 98.6%     0+0k 0+0io 201pf+0w

2.95.3
------
8.520u 0.000s 0:08.69 98.0%     0+0k 0+0io 93pf+0w

mainline
--------
13.780u 0.020s 0:14.04 98.2%    0+0k 0+0io 201pf+0w

//
//
//--------------
//"un-shared assign"

#include <string>
int main()
{
  std::string one, two;

  for (int i = 0; i < 2000000; ++i)
    {
      one = "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890";
      two.assign(one, 19, 80);
      two.assign(one, 9, 60);
      two.assign(one, 39, 10);
      two.assign(one, 0, 10);
    }
}

mainline + this patch
---------------------
7.860u 0.020s 0:07.99 98.6%     0+0k 0+0io 202pf+0w

2.95.3
------
7.960u 0.020s 0:08.10 98.5%     0+0k 0+0io 93pf+0w

mainline
--------
12.640u 0.030s 0:12.84 98.6%    0+0k 0+0io 201pf+0w

//------------------

diff -prN libstdc++-v3-orig/include/bits/basic_string.h
libstdc++-v3/include/bits/basic_string.h
*** libstdc++-v3-orig/include/bits/basic_string.h Mon Dec 10 15:32:28 2001
--- libstdc++-v3/include/bits/basic_string.h Fri Dec 14 12:25:42 2001
*************** namespace std
*** 477,484 ****

        basic_string&
        assign(const basic_string& __str, size_type __pos, size_type __n)
!       {
!  return this->assign(__str._M_check(__pos), __str._M_fold(__pos, __n));
        }

        basic_string&
--- 477,502 ----

        basic_string&
        assign(const basic_string& __str, size_type __pos, size_type __n)
!       {
!  if (__pos > __str.size())
!    __throw_out_of_range("basic_string::assign");
!  if (_M_rep()->_M_is_shared() || _M_rep() != __str._M_rep())
!    return _M_replace_safe(_M_ibegin(), _M_iend(),
!      __str._M_check(__pos),
!      __str._M_fold(__pos, __n));
!  else
!    {
!      // Work in-place.
!      bool __testn = __n < __str.size() - __pos;
!      const size_type __newsize = __testn ? __n : __str.size() - __pos;
!      // Avoid memmove, if possible.
!      if (__pos >= __newsize)
!        traits_type::copy(_M_data(), __str._M_data() + __pos, __newsize);
!      else
!        traits_type::move(_M_data(), __str._M_data() + __pos, __newsize);
!      _M_rep()->_M_length = __newsize;
!      return *this;
!    }
        }

        basic_string&
diff -prN libstdc++-v3-orig/testsuite/21_strings/assign.cc
libstdc++-v3/testsuite/21_strings/assign.cc
*** libstdc++-v3-orig/testsuite/21_strings/assign.cc Wed Oct 31 09:27:20 2001
--- libstdc++-v3/testsuite/21_strings/assign.cc Fri Dec 14 12:26:12 2001
*************** test01()
*** 39,46 ****
--- 39,76 ----
    VERIFY(aux == "Hawaii");
  }

+ void
+ test02()
+ {
+   bool test = true;
+
+   using namespace std;
+
+   string one = "Selling England by the pound";
+   string two = one;
+   string three = "Brilliant trees";
+
+   one.assign(one, 8, 100);
+   VERIFY(one == "England by the pound");
+
+   one.assign(one, 8, 0);
+   VERIFY(one == "");
+   VERIFY(one.capacity() == 20);
+
+   one.assign(two, 8, 7);
+   VERIFY(one == "England");
+
+   one.assign(three, 10, 100);
+   VERIFY(one == "trees");
+
+   three.assign(one, 0, 3);
+   VERIFY(three == "tre");
+ }
+
  int main()
  {
    test01();
+   test02();
+
    return 0;
  }




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