Skip to content

Commit 9b9dbda

Browse files
committed
[libc++] Optimize multi{map,set}::insert
1 parent d70e50b commit 9b9dbda

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

libcxx/include/__tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,35 @@ public:
970970
__emplace_hint_multi(__p, std::move(__value));
971971
}
972972

973+
template <class _InIter, class _Sent>
974+
_LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) {
975+
if (__first == __last)
976+
return;
977+
978+
if (__root() == nullptr) { // Make sure we always have a root node
979+
__node_holder __node = __construct_node(*__first);
980+
__insert_node_at(__end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__node.release()));
981+
++__first;
982+
}
983+
984+
auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root())));
985+
986+
for (; __first != __last; ++__first) {
987+
__node_holder __node = __construct_node(*__first);
988+
// Always check the max node first. This optimizes for sorted ranges inserted at the end.
989+
if (!value_comp()(__node->__get_value(), __max_node->__get_value())) { // __node >= __max_val
990+
__insert_node_at(static_cast<__end_node_pointer>(__max_node),
991+
__max_node->__right_,
992+
static_cast<__node_base_pointer>(__node.get()));
993+
__max_node = __node.release();
994+
} else {
995+
__end_node_pointer __parent;
996+
__node_base_pointer& __child = __find_leaf_high(__parent, __node->__value_);
997+
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__node.release()));
998+
}
999+
}
1000+
}
1001+
9731002
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_assign_unique(const value_type& __v, __node_pointer __dest);
9741003

9751004
_LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);

libcxx/include/map

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
593593
# include <__memory/unique_ptr.h>
594594
# include <__memory_resource/polymorphic_allocator.h>
595595
# include <__node_handle>
596+
# include <__ranges/access.h>
596597
# include <__ranges/concepts.h>
597598
# include <__ranges/container_compatible_range.h>
598599
# include <__ranges/from_range.h>
@@ -1749,17 +1750,13 @@ public:
17491750

17501751
template <class _InputIterator>
17511752
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) {
1752-
for (const_iterator __e = cend(); __f != __l; ++__f)
1753-
__tree_.__emplace_hint_multi(__e.__i_, *__f);
1753+
__tree_.__insert_range_multi(__f, __l);
17541754
}
17551755

17561756
# if _LIBCPP_STD_VER >= 23
17571757
template <_ContainerCompatibleRange<value_type> _Range>
17581758
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
1759-
const_iterator __end = cend();
1760-
for (auto&& __element : __range) {
1761-
__tree_.__emplace_hint_multi(__end.__i_, std::forward<decltype(__element)>(__element));
1762-
}
1759+
__tree_.__insert_range_multi(ranges::begin(__range), ranges::end(__range));
17631760
}
17641761
# endif
17651762

libcxx/include/set

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
530530
# include <__memory/allocator_traits.h>
531531
# include <__memory_resource/polymorphic_allocator.h>
532532
# include <__node_handle>
533+
# include <__ranges/access.h>
533534
# include <__ranges/concepts.h>
534535
# include <__ranges/container_compatible_range.h>
535536
# include <__ranges/from_range.h>
@@ -1205,18 +1206,14 @@ public:
12051206
}
12061207

12071208
template <class _InputIterator>
1208-
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) {
1209-
for (const_iterator __e = cend(); __f != __l; ++__f)
1210-
__tree_.__emplace_hint_multi(__e, *__f);
1209+
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
1210+
__tree_.__insert_range_multi(__first, __last);
12111211
}
12121212

12131213
# if _LIBCPP_STD_VER >= 23
12141214
template <_ContainerCompatibleRange<value_type> _Range>
12151215
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
1216-
const_iterator __end = cend();
1217-
for (auto&& __element : __range) {
1218-
__tree_.__emplace_hint_multi(__end, std::forward<decltype(__element)>(__element));
1219-
}
1216+
__tree_.__insert_range_multi(ranges::begin(__range), ranges::end(__range));
12201217
}
12211218
# endif
12221219

0 commit comments

Comments
 (0)