///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2007-2009 // // 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/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// //Includes for tests #include #include #include #include #include #include #include using namespace boost::posix_time; //[perf_list_value_type //Iteration and element count defines const int NumIter = 100; const int NumElements = 50000; using namespace boost::intrusive; template struct filler { int dummy[10]; }; template <> struct filler {}; template //The object for non-intrusive containers struct test_class : private filler { int i_; test_class() {} test_class(int i) : i_(i) {} friend bool operator <(const test_class &l, const test_class &r) { return l.i_ < r.i_; } friend bool operator >(const test_class &l, const test_class &r) { return l.i_ > r.i_; } }; template struct itest_class //The object for intrusive containers : public list_base_hook >, public test_class { itest_class() {} itest_class(int i) : test_class(i) {} }; template //Adapts functors taking values to functors taking pointers struct func_ptr_adaptor : public FuncObj { typedef typename FuncObj::first_argument_type* first_argument_type; typedef typename FuncObj::second_argument_type* second_argument_type; typedef typename FuncObj::result_type result_type; result_type operator()(first_argument_type a, second_argument_type b) const { return FuncObj::operator()(*a, *b); } }; //] template struct get_ilist //Helps to define an intrusive list from a policy { typedef list, constant_time_size > type; }; template //Helps to define an std list struct get_list { typedef std::list > type; }; template //Helps to define an std pointer list struct get_ptrlist { typedef std::list*> type; }; //////////////////////////////////////////////////////////////////////// // // PUSH_BACK // //////////////////////////////////////////////////////////////////////// template void test_intrusive_list_push_back() { typedef typename get_ilist::type ilist; ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ //First create the elements and insert them in the intrusive list //[perf_list_push_back_intrusive std::vector objects(NumElements); ilist l; for(int i = 0; i < NumElements; ++i) l.push_back(objects[i]); //Elements are unlinked in ilist's destructor //Elements are destroyed in vector's destructor //] } ptime tend = microsec_clock::universal_time(); std::cout << "link_mode: " << LinkMode << ", usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_std_list_push_back() { typedef typename get_list::type stdlist; ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ //Now create the std list and insert //[perf_list_push_back_stdlist stdlist l; for(int i = 0; i < NumElements; ++i) l.push_back(typename stdlist::value_type(i)); //Elements unlinked and destroyed in stdlist's destructor //] } ptime tend = microsec_clock::universal_time(); std::cout << "std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_compact_std_ptrlist_push_back() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //Now measure insertion time, including element creation ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ //Create elements and insert their pointer in the list //[perf_list_push_back_stdptrlist std::vector objects(NumElements); stdptrlist l; for(int i = 0; i < NumElements; ++i) l.push_back(&objects[i]); //Pointers to elements unlinked and destroyed in stdptrlist's destructor //Elements destroyed in vector's destructor //] } ptime tend = microsec_clock::universal_time(); std::cout << "compact std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_disperse_std_ptrlist_push_back() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //Now measure insertion time, including element creation ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ //Create elements and insert their pointer in the list //[perf_list_push_back_disperse_stdptrlist stdlist objects; stdptrlist l; for(int i = 0; i < NumElements; ++i){ objects.push_back(typename stdlist::value_type(i)); l.push_back(&objects.back()); } //Pointers to elements unlinked and destroyed in stdptrlist's destructor //Elements unlinked and destroyed in stdlist's destructor //] } ptime tend = microsec_clock::universal_time(); std::cout << "disperse std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } //////////////////////////////////////////////////////////////////////// // // REVERSE // //////////////////////////////////////////////////////////////////////// //[perf_list_reverse template void test_intrusive_list_reverse() { typedef typename get_ilist::type ilist; //First create the elements std::vector objects(NumElements); //Now create the intrusive list and insert data ilist l(objects.begin(), objects.end()); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ l.reverse(); } ptime tend = microsec_clock::universal_time(); std::cout << "link_mode: " << LinkMode << ", usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_std_list_reverse() { typedef typename get_list::type stdlist; //Create the list and insert values stdlist l; for(int i = 0; i < NumElements; ++i) l.push_back(typename stdlist::value_type()); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ l.reverse(); } ptime tend = microsec_clock::universal_time(); std::cout << "std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_compact_std_ptrlist_reverse() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements std::vector objects(NumElements); //Now create the std list and insert stdptrlist l; for(int i = 0; i < NumElements; ++i) l.push_back(&objects[i]); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ l.reverse(); } ptime tend = microsec_clock::universal_time(); std::cout << "compact std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_disperse_std_ptrlist_reverse() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements std::list objects; //Now create the std list and insert stdptrlist l; for(int i = 0; i < NumElements; ++i){ objects.push_back(typename stdlist::value_type()); l.push_back(&objects.back()); } //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ l.reverse(); } ptime tend = microsec_clock::universal_time(); std::cout << "disperse std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } //] //////////////////////////////////////////////////////////////////////// // // SORT // //////////////////////////////////////////////////////////////////////// //[perf_list_sort template void test_intrusive_list_sort() { typedef typename get_ilist::type ilist; //First create the elements std::vector objects(NumElements); for(int i = 0; i < NumElements; ++i) objects[i].i_ = i; //Now create the intrusive list and insert data ilist l(objects.begin(), objects.end()); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ if(!(i % 2)){ l.sort(std::greater()); } else{ l.sort(std::less()); } } ptime tend = microsec_clock::universal_time(); std::cout << "link_mode: " << LinkMode << ", usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_std_list_sort() { typedef typename get_list::type stdlist; //Create the list and insert values stdlist l; for(int i = 0; i < NumElements; ++i) l.push_back(typename stdlist::value_type(i)); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ if(!(i % 2)){ l.sort(std::greater()); } else{ l.sort(std::less()); } } ptime tend = microsec_clock::universal_time(); std::cout << "std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_compact_std_ptrlist_sort() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements std::vector objects(NumElements); for(int i = 0; i < NumElements; ++i) objects[i].i_ = i; //Now create the std list and insert stdptrlist l; for(int i = 0; i < NumElements; ++i) l.push_back(&objects[i]); //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ if(!(i % 2)){ l.sort(func_ptr_adaptor >()); } else{ l.sort(func_ptr_adaptor >()); } } ptime tend = microsec_clock::universal_time(); std::cout << "compact std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_disperse_std_ptrlist_sort() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements and the list std::list objects; stdptrlist l; for(int i = 0; i < NumElements; ++i){ objects.push_back(typename stdlist::value_type(i)); l.push_back(&objects.back()); } //Now measure sorting time ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ if(!(i % 2)){ l.sort(func_ptr_adaptor >()); } else{ l.sort(func_ptr_adaptor >()); } } ptime tend = microsec_clock::universal_time(); std::cout << "disperse std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } //] //////////////////////////////////////////////////////////////////////// // // WRITE ACCESS // //////////////////////////////////////////////////////////////////////// //[perf_list_write_access template void test_intrusive_list_write_access() { typedef typename get_ilist::type ilist; //First create the elements std::vector objects(NumElements); for(int i = 0; i < NumElements; ++i){ objects[i].i_ = i; } //Now create the intrusive list and insert data ilist l(objects.begin(), objects.end()); //Now measure access time to the value type ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ typename ilist::iterator it(l.begin()), end(l.end()); for(; it != end; ++it){ ++(it->i_); } } ptime tend = microsec_clock::universal_time(); std::cout << "link_mode: " << LinkMode << ", usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_std_list_write_access() { typedef typename get_list::type stdlist; //Create the list and insert values stdlist l; for(int i = 0; i < NumElements; ++i) l.push_back(typename stdlist::value_type(i)); //Now measure access time to the value type ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ typename stdlist::iterator it(l.begin()), end(l.end()); for(; it != end; ++it){ ++(it->i_); } } ptime tend = microsec_clock::universal_time(); std::cout << "std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_compact_std_ptrlist_write_access() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements std::vector objects(NumElements); for(int i = 0; i < NumElements; ++i){ objects[i].i_ = i; } //Now create the std list and insert stdptrlist l; for(int i = 0; i < NumElements; ++i) l.push_back(&objects[i]); //Now measure access time to the value type ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ typename stdptrlist::iterator it(l.begin()), end(l.end()); for(; it != end; ++it){ ++((*it)->i_); } } ptime tend = microsec_clock::universal_time(); std::cout << "compact std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } template void test_disperse_std_ptrlist_write_access() { typedef typename get_list::type stdlist; typedef typename get_ptrlist::type stdptrlist; //First create the elements std::list objects; //Now create the std list and insert stdptrlist l; for(int i = 0; i < NumElements; ++i){ objects.push_back(typename stdlist::value_type(i)); l.push_back(&objects.back()); } //Now measure access time to the value type ptime tini = microsec_clock::universal_time(); for(int i = 0; i < NumIter; ++i){ typename stdptrlist::iterator it(l.begin()), end(l.end()); for(; it != end; ++it){ ++((*it)->i_); } } ptime tend = microsec_clock::universal_time(); std::cout << "disperse std::list usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; } //] //////////////////////////////////////////////////////////////////////// // // ALL TESTS // //////////////////////////////////////////////////////////////////////// template void do_all_tests() { std::cout << "\n\nTesting push back() with BigSize:" << BigSize << std::endl; test_intrusive_list_push_back(); test_intrusive_list_push_back(); test_intrusive_list_push_back(); test_std_list_push_back (); test_compact_std_ptrlist_push_back(); test_disperse_std_ptrlist_push_back(); //reverse std::cout << "\n\nTesting reverse() with BigSize:" << BigSize << std::endl; test_intrusive_list_reverse(); test_intrusive_list_reverse(); test_intrusive_list_reverse(); test_std_list_reverse(); test_compact_std_ptrlist_reverse(); test_disperse_std_ptrlist_reverse(); //sort std::cout << "\n\nTesting sort() with BigSize:" << BigSize << std::endl; test_intrusive_list_sort(); test_intrusive_list_sort(); test_intrusive_list_sort(); test_std_list_sort(); test_compact_std_ptrlist_sort(); test_disperse_std_ptrlist_sort(); //write_access std::cout << "\n\nTesting write_access() with BigSize:" << BigSize << std::endl; test_intrusive_list_write_access(); test_intrusive_list_write_access(); test_intrusive_list_write_access(); test_std_list_write_access(); test_compact_std_ptrlist_write_access(); test_disperse_std_ptrlist_write_access(); } int main() { //First pass the tests with a small size class do_all_tests(); //Now pass the tests with a big size class do_all_tests(); return 0; } #include