re PR libstdc++/19433 (set, multiset, map, multimap misuse hint on insert)

2005-01-17  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/19433
	* include/bits/stl_tree.h (_Rb_tree<>::insert_unique(iterator,
	const _Val&), _Rb_tree<>::insert_equal(iterator, const _Val&)):
	Obtain amortized constant complexity if t is inserted right after
	p - not before p - as per Table 69.
	* testsuite/performance/23_containers/set_insert_from_sorted.cc: New.

	* testsuite/23_containers/multiset/insert/2.cc: New.
	* testsuite/23_containers/set/insert/1.cc: Likewise.

	* testsuite/performance/23_containers/set_create_from_sorted.cc:
	Simplify.

	* include/bits/stl_tree.h: Add a few missing std:: qualifications.

From-SVN: r93761
This commit is contained in:
Paolo Carlini 2005-01-17 14:14:26 +00:00 committed by Paolo Carlini
parent ef9312c1c7
commit ac317859d4
6 changed files with 308 additions and 66 deletions

View File

@ -1,3 +1,20 @@
2005-01-17 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/19433
* include/bits/stl_tree.h (_Rb_tree<>::insert_unique(iterator,
const _Val&), _Rb_tree<>::insert_equal(iterator, const _Val&)):
Obtain amortized constant complexity if t is inserted right after
p - not before p - as per Table 69.
* testsuite/performance/23_containers/set_insert_from_sorted.cc: New.
* testsuite/23_containers/multiset/insert/2.cc: New.
* testsuite/23_containers/set/insert/1.cc: Likewise.
* testsuite/performance/23_containers/set_create_from_sorted.cc:
Simplify.
* include/bits/stl_tree.h: Add a few missing std:: qualifications.
2005-01-16 Jonathan Wakely <redi@gcc.gnu.org>
* include/ext/rope: Qualify calls to std::copy() by sequence_buffer.

View File

@ -1,6 +1,6 @@
// RB tree implementation -*- C++ -*-
// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
// Copyright (C) 2001, 2002, 2003, 2004, 2005 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
@ -708,7 +708,7 @@ namespace std
const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
{
return __x.size() == __y.size()
&& equal(__x.begin(), __x.end(), __y.begin());
&& std::equal(__x.begin(), __x.end(), __y.begin());
}
template<typename _Key, typename _Val, typename _KeyOfValue,
@ -717,7 +717,7 @@ namespace std
operator<(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
{
return lexicographical_compare(__x.begin(), __x.end(),
return std::lexicographical_compare(__x.begin(), __x.end(),
__y.begin(), __y.end());
}
@ -892,21 +892,11 @@ namespace std
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
insert_unique(iterator __position, const _Val& __v)
{
if (__position._M_node == _M_leftmost())
if (__position._M_node == _M_end()
|| __position._M_node == _M_rightmost())
{
// begin()
if (size() > 0
&& _M_impl._M_key_compare(_KeyOfValue()(__v),
_S_key(__position._M_node)))
return _M_insert(__position._M_node, __position._M_node, __v);
// First argument just needs to be non-null.
else
return insert_unique(__v).first;
}
else if (__position._M_node == _M_end())
{
// end()
if (_M_impl._M_key_compare(_S_key(_M_rightmost()),
&& _M_impl._M_key_compare(_S_key(_M_rightmost()),
_KeyOfValue()(__v)))
return _M_insert(0, _M_rightmost(), __v);
else
@ -914,17 +904,17 @@ namespace std
}
else
{
iterator __before = __position;
--__before;
if (_M_impl._M_key_compare(_S_key(__before._M_node),
iterator __after = __position;
++__after;
if (_M_impl._M_key_compare(_S_key(__position._M_node),
_KeyOfValue()(__v))
&& _M_impl._M_key_compare(_KeyOfValue()(__v),
_S_key(__position._M_node)))
_S_key(__after._M_node)))
{
if (_S_right(__before._M_node) == 0)
return _M_insert(0, __before._M_node, __v);
if (_S_right(__position._M_node) == 0)
return _M_insert(0, __position._M_node, __v);
else
return _M_insert(__position._M_node, __position._M_node, __v);
return _M_insert(__after._M_node, __after._M_node, __v);
// First argument just needs to be non-null.
}
else
@ -938,21 +928,11 @@ namespace std
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
insert_equal(iterator __position, const _Val& __v)
{
if (__position._M_node == _M_leftmost())
if (__position._M_node == _M_end()
|| __position._M_node == _M_rightmost())
{
// begin()
if (size() > 0
&& !_M_impl._M_key_compare(_S_key(__position._M_node),
_KeyOfValue()(__v)))
return _M_insert(__position._M_node, __position._M_node, __v);
// first argument just needs to be non-null
else
return insert_equal(__v);
}
else if (__position._M_node == _M_end())
{
// end()
if (!_M_impl._M_key_compare(_KeyOfValue()(__v),
&& !_M_impl._M_key_compare(_KeyOfValue()(__v),
_S_key(_M_rightmost())))
return _M_insert(0, _M_rightmost(), __v);
else
@ -960,17 +940,17 @@ namespace std
}
else
{
iterator __before = __position;
--__before;
iterator __after = __position;
++__after;
if (!_M_impl._M_key_compare(_KeyOfValue()(__v),
_S_key(__before._M_node))
&& !_M_impl._M_key_compare(_S_key(__position._M_node),
_S_key(__position._M_node))
&& !_M_impl._M_key_compare(_S_key(__after._M_node),
_KeyOfValue()(__v)))
{
if (_S_right(__before._M_node) == 0)
return _M_insert(0, __before._M_node, __v);
if (_S_right(__position._M_node) == 0)
return _M_insert(0, __position._M_node, __v);
else
return _M_insert(__position._M_node, __position._M_node, __v);
return _M_insert(__after._M_node, __after._M_node, __v);
// First argument just needs to be non-null.
}
else

View File

@ -0,0 +1,97 @@
// 2005-01-17 Paolo Carlini <pcarlini@suse.de>
// Copyright (C) 2005 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 <set>
#include <testsuite_hooks.h>
// A few tests for insert with hint, in the occasion of libstdc++/19422
// and libstdc++/19433.
void test01()
{
bool test __attribute__((unused)) = true;
using namespace std;
multiset<int> ms0, ms1;
multiset<int>::iterator iter1;
ms0.insert(1);
ms1.insert(ms1.end(), 1);
VERIFY( ms0 == ms1 );
ms0.insert(3);
ms1.insert(ms1.begin(), 3);
VERIFY( ms0 == ms1 );
ms0.insert(4);
iter1 = ms1.insert(ms1.end(), 4);
VERIFY( ms0 == ms1 );
ms0.insert(6);
ms1.insert(iter1, 6);
VERIFY( ms0 == ms1 );
ms0.insert(2);
ms1.insert(ms1.begin(), 2);
VERIFY( ms0 == ms1 );
ms0.insert(7);
ms1.insert(ms1.end(), 7);
VERIFY( ms0 == ms1 );
ms0.insert(5);
ms1.insert(ms1.find(4), 5);
VERIFY( ms0 == ms1 );
ms0.insert(0);
ms1.insert(ms1.end(), 0);
VERIFY( ms0 == ms1 );
ms0.insert(8);
ms1.insert(ms1.find(3), 8);
VERIFY( ms0 == ms1 );
ms0.insert(9);
ms1.insert(ms1.end(), 9);
VERIFY( ms0 == ms1 );
ms0.insert(10);
ms1.insert(ms1.begin(), 10);
VERIFY( ms0 == ms1 );
}
#if !__GXX_WEAK__ && _MT_ALLOCATOR_H
// Explicitly instantiate for systems with no COMDAT or weak support.
template class __gnu_cxx::__mt_alloc<std::_Rb_tree_node<int> >;
#endif
int main ()
{
test01();
return 0;
}

View File

@ -0,0 +1,97 @@
// 2005-01-17 Paolo Carlini <pcarlini@suse.de>
// Copyright (C) 2005 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 <set>
#include <testsuite_hooks.h>
// A few tests for insert with hint, in the occasion of libstdc++/19422
// and libstdc++/19433.
void test01()
{
bool test __attribute__((unused)) = true;
using namespace std;
set<int> s0, s1;
set<int>::iterator iter1;
s0.insert(1);
s1.insert(s1.end(), 1);
VERIFY( s0 == s1 );
s0.insert(3);
s1.insert(s1.begin(), 3);
VERIFY( s0 == s1 );
s0.insert(4);
iter1 = s1.insert(s1.end(), 4);
VERIFY( s0 == s1 );
s0.insert(6);
s1.insert(iter1, 6);
VERIFY( s0 == s1 );
s0.insert(2);
s1.insert(s1.begin(), 2);
VERIFY( s0 == s1 );
s0.insert(7);
s1.insert(s1.end(), 7);
VERIFY( s0 == s1 );
s0.insert(5);
s1.insert(s1.find(4), 5);
VERIFY( s0 == s1 );
s0.insert(0);
s1.insert(s1.end(), 0);
VERIFY( s0 == s1 );
s0.insert(8);
s1.insert(s1.find(3), 8);
VERIFY( s0 == s1 );
s0.insert(9);
s1.insert(s1.end(), 9);
VERIFY( s0 == s1 );
s0.insert(10);
s1.insert(s1.begin(), 10);
VERIFY( s0 == s1 );
}
#if !__GXX_WEAK__ && _MT_ALLOCATOR_H
// Explicitly instantiate for systems with no COMDAT or weak support.
template class __gnu_cxx::__mt_alloc<std::_Rb_tree_node<int> >;
#endif
int main ()
{
test01();
return 0;
}

View File

@ -27,11 +27,9 @@
#include <vector>
#include <set>
#include <list>
#include <sstream>
#include <testsuite_performance.h>
// adjust for your setup
static const unsigned max_size = 1000000; // avoid excessive swap file use!
static const unsigned iterations = 10; // make results less random while
static const unsigned step = 50000; // keeping the total time reasonable
@ -45,19 +43,17 @@ int main()
resource_counter resource;
typedef set<unsigned> the_set;
typedef list<unsigned> the_list;
vector<unsigned> v(max_size, 0);
for (unsigned i = 0; i != max_size; ++i)
v[i] = i; // initialize sorted array
report_header(__FILE__, "set:");
for (unsigned count = step; count <= max_size; count += step)
{
ostringstream oss;
oss << count;
// measure set construction time
// measure set construction time (linear in count (Table 69))
start_counters(time, resource);
for (unsigned i = 0; i != iterations; ++i)
the_set(v.begin(), v.begin() + count);
@ -65,19 +61,4 @@ int main()
report_performance(__FILE__, oss.str(), time, resource);
clear_counters(time, resource);
}
report_header(__FILE__, "list:");
for (unsigned count = step; count <= max_size; count += step)
{
ostringstream oss;
oss << count;
// measure list construction time (surely linear in count)
start_counters(time, resource);
for (unsigned i = 0; i != iterations; ++i)
the_list(v.begin(), v.begin() + count);
stop_counters(time, resource);
report_performance(__FILE__, oss.str(), time, resource);
clear_counters(time, resource);
}
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2005 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 <vector>
#include <set>
#include <sstream>
#include <testsuite_performance.h>
static const unsigned max_size = 1000000; // avoid excessive swap file use!
static const unsigned iterations = 10; // make results less random while
static const unsigned step = 50000; // keeping the total time reasonable
// libstdc++/19433
int main()
{
using namespace std;
using namespace __gnu_test;
time_counter time;
resource_counter resource;
typedef set<unsigned> the_set;
vector<unsigned> v(max_size, 0);
for (unsigned i = 0; i != max_size; ++i)
v[i] = i; // initialize sorted array
for (unsigned count = step; count <= max_size; count += step)
{
ostringstream oss;
oss << count;
start_counters(time, resource);
for (unsigned i = 0; i != iterations; ++i)
{
the_set test_set;
the_set::iterator iter = test_set.end();
// each insert in amortized constant time (Table 69)
for (unsigned j = 0; j != count; ++j)
iter = test_set.insert(iter, v[j]);
}
stop_counters(time, resource);
report_performance(__FILE__, oss.str(), time, resource);
clear_counters(time, resource);
}
}