This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] Assign(_str, _pos, _n) (take2) + benchmarks
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: libstdc++ at gcc dot gnu dot org
- Cc: ncm at cantrip dot org, bkoz at redhat dot com
- Date: Fri, 14 Dec 2001 12:43:02 +0100
- Subject: [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;
}