Optimize merge and sort with the utility unused_storage

This commit is contained in:
Ion Gaztañaga
2024-09-09 00:40:15 +02:00
parent bd8c8b0327
commit 69136f9967
2 changed files with 48 additions and 33 deletions

View File

@@ -121,6 +121,7 @@ namespace boost {
namespace container { namespace container {
namespace dtl { namespace dtl {
/////////////////////////////////////// ///////////////////////////////////////
// //
// Helper functions to merge elements // Helper functions to merge elements
@@ -139,13 +140,18 @@ inline void flat_tree_container_inplace_merge //is_contiguous_container == true
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_) (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
{ {
typedef typename SequenceContainer::value_type value_type; typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
value_type *const braw = boost::movelib::to_raw_pointer(dest.data()); value_type *const braw = boost::movelib::to_raw_pointer(dest.data());
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it); value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
//Don't use iterator_to_raw_pointer for end as debug iterators can assert when //Don't use iterator_to_raw_pointer for end as debug iterators can assert when
//"operator ->" is used with the end iterator //"operator ->" is used with the end iterator
value_type *const eraw = braw + dest.size(); value_type *const eraw = braw + dest.size();
size_type dest_unused_storage_size = 0;
value_type *const dest_unused_storage_addr =
unused_storage<SequenceContainer>::get(dest, dest_unused_storage_size);
boost::movelib::adaptive_merge boost::movelib::adaptive_merge
(braw, iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest)); (braw, iraw, eraw, comp, dest_unused_storage_addr, dest_unused_storage_size);
} }
template<class SequenceContainer, class Compare> template<class SequenceContainer, class Compare>
@@ -165,14 +171,18 @@ inline void flat_tree_container_inplace_sort_ending //is_contiguous_container ==
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_) (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
{ {
typedef typename SequenceContainer::value_type value_type; typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it); value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
//Don't use iterator_to_raw_pointer for end as debug iterators can assert when //Don't use iterator_to_raw_pointer for end as debug iterators can assert when
//"operator ->" is used with the end iterator //"operator ->" is used with the end iterator
value_type* const eraw = boost::movelib::to_raw_pointer(dest.data()) + dest.size(); value_type* const eraw = boost::movelib::to_raw_pointer(dest.data()) + dest.size();
size_type dest_unused_storage_size;
value_type* const dest_unused_storage_addr =
unused_storage<SequenceContainer>::get(dest, dest_unused_storage_size);
boost::movelib::adaptive_sort boost::movelib::adaptive_sort
(iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest)); (iraw, eraw, comp, dest_unused_storage_addr, dest_unused_storage_size);
} }
template<class SequenceContainer, class Compare> template<class SequenceContainer, class Compare>
@@ -320,23 +330,24 @@ template<class SequenceContainer, class Compare>
void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp) (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
{ {
if(tseq.capacity() >= (seq.capacity() - seq.size())) { typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
size_type tseq_unused_storage_size, seq_unused_storage_size;
value_type* const tseq_unused_storage_addr =
unused_storage<SequenceContainer>::get(tseq, tseq_unused_storage_size);
value_type* const seq_unused_storage_addr =
unused_storage<SequenceContainer>::get(seq, seq_unused_storage_size);
tseq.clear(); tseq.clear();
const bool use_tseq_storage = tseq_unused_storage_size > seq_unused_storage_size;
boost::movelib::adaptive_sort boost::movelib::adaptive_sort
(boost::movelib::iterator_to_raw_pointer(seq.begin()) ( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end()) , boost::movelib::iterator_to_raw_pointer(seq.end())
, comp , comp
, boost::movelib::iterator_to_raw_pointer(tseq.begin()) , use_tseq_storage ? tseq_unused_storage_addr : seq_unused_storage_addr
, tseq.capacity()); , use_tseq_storage ? tseq_unused_storage_size : seq_unused_storage_size);
}
else{
boost::movelib::adaptive_sort
(boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, boost::movelib::iterator_to_raw_pointer(seq.end())
, seq.capacity() - seq.size());
}
} }
template<class SequenceContainer, class Compare> template<class SequenceContainer, class Compare>

View File

@@ -31,9 +31,9 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp> #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//back_free_capacity //free_storage
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME back_free_capacity #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME unused_storage
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace back_free_capacity_detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace unused_storage_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
@@ -60,19 +60,23 @@ struct is_contiguous_container
template < class Container template < class Container
, bool = boost::container::back_free_capacity_detail:: , bool = boost::container::unused_storage_detail::
has_member_function_callable_with_back_free_capacity<const Container>::value> has_member_function_callable_with_unused_storage<const Container>::value>
struct back_free_capacity struct unused_storage
{ {
static typename Container::size_type get(const Container &c) static typename Container::value_type* get(Container &c, typename Container::size_type &s)
{ return c.back_free_capacity(); } { return c.unused_storage(s); }
}; };
template < class Container> template < class Container>
struct back_free_capacity<Container, false> struct unused_storage<Container, false>
{ {
static typename Container::size_type get(const Container &c) static typename Container::value_type* get(Container&, typename Container::size_type &s)
{ return c.capacity() - c.size(); } {
s = 0;
return 0;
}
}; };
} //namespace dtl { } //namespace dtl {