From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- src/boost/libs/multi_index/perf/Jamfile.v2 | 14 + src/boost/libs/multi_index/perf/test_perf.cpp | 545 ++++++++++++++++++++++++++ 2 files changed, 559 insertions(+) create mode 100644 src/boost/libs/multi_index/perf/Jamfile.v2 create mode 100644 src/boost/libs/multi_index/perf/test_perf.cpp (limited to 'src/boost/libs/multi_index/perf') diff --git a/src/boost/libs/multi_index/perf/Jamfile.v2 b/src/boost/libs/multi_index/perf/Jamfile.v2 new file mode 100644 index 00000000..c9aea9c7 --- /dev/null +++ b/src/boost/libs/multi_index/perf/Jamfile.v2 @@ -0,0 +1,14 @@ +# Boost.MultiIndex performance tests Jamfile +# +# Copyright 2003-2006 Joaquín M López Muñoz. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# See http://www.boost.org/libs/multi_index for library home page. + +exe test_perf + : test_perf.cpp + : $(BOOST_ROOT) + : release + ; diff --git a/src/boost/libs/multi_index/perf/test_perf.cpp b/src/boost/libs/multi_index/perf/test_perf.cpp new file mode 100644 index 00000000..7b244178 --- /dev/null +++ b/src/boost/libs/multi_index/perf/test_perf.cpp @@ -0,0 +1,545 @@ +/* Boost.MultiIndex performance test. + * + * Copyright 2003-2013 Joaquin M Lopez Munoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org/libs/multi_index for library home page. + */ + +#include /* keep it first to prevent nasty warns in MSVC */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost::multi_index; + +/* Measurement harness by Andrew Koenig, extracted from companion code to + * Stroustrup, B.: "Wrapping C++ Member Function Calls", The C++ Report, + * June 2000, Vol 12/No 6. + * Original code retrievable at: http://www.research.att.com/~bs/wrap_code.cpp + */ + +// How many clock units does it take to interrogate the clock? +static double clock_overhead() +{ + clock_t k = clock(), start, limit; + + // Wait for the clock to tick + do start = clock(); + while (start == k); + + // interrogate the clock until it has advanced at least a second + // (for reasonable accuracy) + limit = start + CLOCKS_PER_SEC; + + unsigned long r = 0; + while ((k = clock()) < limit) + ++r; + + return double(k - start) / r; +} + +// We'd like the odds to be factor:1 that the result is +// within percent% of the median +const int factor = 10; +const int percent = 20; + +// Measure a function (object) factor*2 times, +// appending the measurements to the second argument +template +void measure_aux(F f, vector& mv) +{ + static double ovhd = clock_overhead(); + + // Ensure we don't reallocate in mid-measurement + mv.reserve(mv.size() + factor*2); + + // Wait for the clock to tick + clock_t k = clock(); + clock_t start; + + do start = clock(); + while (start == k); + + // Do 2*factor measurements + for (int i = 2*factor; i; --i) { + unsigned long count = 0, limit = 1, tcount = 0; + + // Original code used CLOCKS_PER_SEC/100 + const clock_t clocklimit = start + CLOCKS_PER_SEC/10; + clock_t t; + + do { + while (count < limit) { + f(); + ++count; + } + limit *= 2; + ++tcount; + } while ((t = clock()) < clocklimit); + + // Wait for the clock to tick again; + clock_t t2; + do ++tcount; + while ((t2 = clock()) == t); + + // Append the measurement to the vector + mv.push_back(((t2 - start) - (tcount * ovhd)) / count); + + // Establish a new starting point + start = t2; + } +} + +// Returns the number of clock units per iteration +// With odds of factor:1, the measurement is within percent% of +// the value returned, which is also the median of all measurements. +template +double measure(F f) +{ + vector mv; + + int n = 0; // iteration counter + do { + ++n; + + // Try 2*factor measurements + measure_aux(f, mv); + assert(mv.size() == 2*n*factor); + + // Compute the median. We know the size is even, so we cheat. + sort(mv.begin(), mv.end()); + double median = (mv[n*factor] + mv[n*factor-1])/2; + + // If the extrema are within threshold of the median, we're done + if (mv[n] > (median * (100-percent))/100 && + mv[mv.size() - n - 1] < (median * (100+percent))/100) + return median; + + } while (mv.size() < factor * 200); + + // Give up! + clog << "Help!\n\n"; + exit(1); +} + +/* dereferencing compare predicate */ + +template +struct it_compare +{ + bool operator()(const Iterator& x,const Iterator& y)const{return comp(*x,*y);} + +private: + Compare comp; +}; + +/* list_wrapper and multiset_wrapper adapt std::lists and std::multisets + * to make them conform to a set-like insert interface which test + * routines do assume. + */ + +template +struct list_wrapper:List +{ + typedef typename List::value_type value_type; + typedef typename List::iterator iterator; + + pair insert(const value_type& v) + { + List::push_back(v); + return pair(boost::prior(List::end()),true); + } +}; + +template +struct multiset_wrapper:Multiset +{ + typedef typename Multiset::value_type value_type; + typedef typename Multiset::iterator iterator; + + pair insert(const value_type& v) + { + return pair(Multiset::insert(v),true); + } +}; + +/* space comsumption of manual simulations is determined by checking + * the node sizes of the containers involved. This cannot be done in a + * portable manner, so node_size has to be written on a per stdlibrary + * basis. Add your own versions if necessary. + */ + +#if defined(BOOST_DINKUMWARE_STDLIB) + +template +size_t node_size(const Container&) +{ + return sizeof(*Container().begin()._Mynode()); +} + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + +template +size_t node_size(const Container&) +{ + typedef typename Container::iterator::_Link_type node_ptr; + node_ptr p=0; + return sizeof(*p); +} + +template +size_t node_size(const list&) +{ + return sizeof(typename list::iterator::_Node); +} + +template +size_t node_size(const list_wrapper&) +{ + return sizeof(typename List::iterator::_Node); +} + +#else + +/* default version returns 0 by convention */ + +template +size_t node_size(const Container&) +{ + return 0; +} + +#endif + +/* mono_container runs the tested routine on multi_index and manual + * simulations comprised of one standard container. + * bi_container and tri_container run the equivalent routine for manual + * compositions of two and three standard containers, respectively. + */ + +template +struct mono_container +{ + mono_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container::iterator iterator; + + Container c; + + for(int i=0;i +struct bi_container +{ + bi_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; + + Container1 c1; + Container2 c2; + + for(int i=0;i +struct tri_container +{ + tri_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; + typedef typename Container3::iterator iterator3; + + Container1 c1; + Container2 c2; + Container3 c3; + + for(int i=0;i +void run_tests(const char* title) +{ + cout< +void compare_structures(const char* title) +{ + run_tests< + mono_container, + mono_container + >(title); +} + +template +void compare_structures2(const char* title) +{ + run_tests< + mono_container, + bi_container + >(title); +} + +template < + typename IndexedType, + typename ManualType1,typename ManualType2,typename ManualType3 +> +void compare_structures3(const char* title) +{ + run_tests< + mono_container, + tri_container + >(title); +} + +int main() +{ + /* some stdlibs provide the discussed but finally rejected std::identity */ + using boost::multi_index::identity; + + { + /* 1 ordered index */ + + typedef multi_index_container indexed_t; + typedef set manual_t; + + compare_structures( + "1 ordered index"); + } + { + /* 1 sequenced index */ + + typedef list_wrapper< + multi_index_container< + int, + indexed_by > + > + > indexed_t; + typedef list_wrapper > manual_t; + + compare_structures( + "1 sequenced index"); + } + { + /* 2 ordered indices */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique >, + ordered_non_unique > + > + > indexed_t; + typedef set manual_t1; + typedef multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + manual_t1::key_compare + > + > manual_t2; + + compare_structures2( + "2 ordered indices"); + } + { + /* 1 ordered index + 1 sequenced index */ + + typedef multi_index_container< + int, + indexed_by< + boost::multi_index::ordered_unique >, + sequenced<> + > + > indexed_t; + typedef list_wrapper< + list + > manual_t1; + typedef multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + std::less + > + > manual_t2; + + compare_structures2( + "1 ordered index + 1 sequenced index"); + } + { + /* 3 ordered indices */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique >, + ordered_non_unique >, + ordered_non_unique > + > + > indexed_t; + typedef set manual_t1; + typedef multiset_wrapper< + multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + manual_t1::key_compare + > + > + > manual_t2; + typedef multiset< + manual_t2::iterator, + it_compare< + manual_t2::iterator, + manual_t2::key_compare + > + > manual_t3; + + compare_structures3( + "3 ordered indices"); + } + { + /* 2 ordered indices + 1 sequenced index */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique >, + ordered_non_unique >, + sequenced<> + > + > indexed_t; + typedef list_wrapper< + list + > manual_t1; + typedef multiset_wrapper< + multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + std::less + > + > + > manual_t2; + typedef multiset< + manual_t2::iterator, + it_compare< + manual_t2::iterator, + manual_t2::key_compare + > + > manual_t3; + + compare_structures3( + "2 ordered indices + 1 sequenced index"); + } + + return 0; +} -- cgit v1.2.3