diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/flyweight/example/perf.cpp | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/flyweight/example/perf.cpp')
-rw-r--r-- | src/boost/libs/flyweight/example/perf.cpp | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/boost/libs/flyweight/example/perf.cpp b/src/boost/libs/flyweight/example/perf.cpp new file mode 100644 index 00000000..3e608c0d --- /dev/null +++ b/src/boost/libs/flyweight/example/perf.cpp @@ -0,0 +1,312 @@ +/* Boost.Flyweight example of performance comparison. + * + * Copyright 2006-2008 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/flyweight for library home page. + */ + +#include <boost/flyweight/flyweight.hpp> +#include <boost/flyweight/hashed_factory.hpp> +#include <boost/flyweight/set_factory.hpp> +#include <boost/flyweight/static_holder.hpp> +#include <boost/flyweight/simple_locking.hpp> +#include <boost/flyweight/refcounted.hpp> +#include <boost/flyweight/no_tracking.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/tokenizer.hpp> +#include <algorithm> +#include <cstddef> +#include <cstdlib> +#include <ctime> +#include <fstream> +#include <iostream> +#include <numeric> +#include <sstream> +#include <string> +#include <vector> + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ +using ::clock; +using ::clock_t; +using ::exit; +} +#endif + +using namespace boost::flyweights; + +/* Instrumented allocator family keeping track of the memory in + * current use. + */ + +std::size_t count_allocator_mem=0; + +template<typename T> +class count_allocator +{ +public: + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template<class U>struct rebind{typedef count_allocator<U> other;}; + + count_allocator(){} + count_allocator(const count_allocator<T>&){} + template<class U>count_allocator(const count_allocator<U>&,int=0){} + + pointer address(reference x)const{return &x;} + const_pointer address(const_reference x)const{return &x;} + + pointer allocate(size_type n,const void* =0) + { + pointer p=(T*)(new char[n*sizeof(T)]); + count_allocator_mem+=n*sizeof(T); + return p; + } + + void deallocate(void* p,size_type n) + { + count_allocator_mem-=n*sizeof(T); + delete [](char *)p; + } + + size_type max_size() const{return (size_type )(-1);} + void construct(pointer p,const T& val){new(p)T(val);} + void destroy(pointer p){p->~T();} + + friend bool operator==(const count_allocator&,const count_allocator&) + { + return true; + } + + friend bool operator!=(const count_allocator&,const count_allocator&) + { + return false; + } +}; + +template<> +class count_allocator<void> +{ +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template<class U>struct rebind{typedef count_allocator<U> other;}; +}; + +/* Define some count_allocator-based types and Boost.Flyweight components */ + +typedef std::basic_string< + char,std::char_traits<char>,count_allocator<char> +> count_string; + +typedef hashed_factory< + boost::hash<boost::mpl::_2>, + std::equal_to<boost::mpl::_2>, + count_allocator<boost::mpl::_1> +> count_hashed_factory; + +typedef set_factory< + std::less<boost::mpl::_2>, + count_allocator<boost::mpl::_1> +> count_set_factory; + +/* Some additional utilities used by the test routine */ + +class timer +{ +public: + timer(){restart();} + + void restart(){t=std::clock();} + + void time(const char* str) + { + std::cout<<str<<": "<<(double)(std::clock()-t)/CLOCKS_PER_SEC<<" s\n"; + } + +private: + std::clock_t t; +}; + +template<typename T> +struct is_flyweight: + boost::mpl::false_{}; + +template< + typename T, + typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5 +> +struct is_flyweight<flyweight<T,Arg1,Arg2,Arg3,Arg4,Arg5> >: + boost::mpl::true_{}; + +struct length_adder +{ + std::size_t operator()(std::size_t n,const count_string& x)const + { + return n+x.size(); + } +}; + +/* Measure time and memory performance for a String, which is assumed + * to be either a plain string type or a string flyweight. + */ + +template<typename String> +struct test +{ + static std::size_t run(const std::string& file) + { + typedef std::vector<String,count_allocator<String> > count_vector; + + /* Define a tokenizer on std::istreambuf. */ + + typedef std::istreambuf_iterator<char> char_iterator; + typedef boost::tokenizer< + boost::char_separator<char>, + char_iterator + > tokenizer; + + std::ifstream ifs(file.c_str()); + if(!ifs){ + std::cout<<"can't open "<<file<<std::endl; + std::exit(EXIT_FAILURE); + } + + /* Initialization; tokenize using space and common punctuaction as + * separators, and keeping the separators. + */ + + timer t; + + tokenizer tok=tokenizer( + char_iterator(ifs),char_iterator(), + boost::char_separator<char>( + "", + "\t\n\r !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")); + count_vector txt; + for(tokenizer::iterator it=tok.begin();it!=tok.end();++it){ + txt.push_back(String(it->c_str())); + } + + t.time("initialization time"); + + /* Assignment */ + + t.restart(); + + count_vector txt2; + for(int i=0;i<10;++i){ + txt2.insert(txt2.end(),txt.begin(),txt.end()); + } + + t.time("assignment time"); + + /* Equality comparison */ + + t.restart(); + + std::size_t c=0; + for(int i=0;i<100;++i){ + c+=std::count(txt.begin(),txt.end(),txt[c%txt.size()]); + } + + t.time("equality comparison time"); + + /* Value access */ + + t.restart(); + + std::size_t s=0; + for(int i=0;i<20;++i){ + s+=std::accumulate(txt2.begin(),txt2.end(),s,length_adder()); + } + + t.time("value access time"); + + std::cout<<"bytes used: "<<count_allocator_mem; + if(is_flyweight<String>::value){ + std::size_t flyweight_mem=(txt.capacity()+txt2.capacity())*sizeof(String); + std::cout<<"= flyweights("<<flyweight_mem + <<")+values("<<count_allocator_mem-flyweight_mem<<")"; + } + std::cout<<"\n"; + + return c+s; + } +}; + +/* table of test cases for the user to select from */ + +struct test_case +{ + const char* name; + std::size_t (*test)(const std::string&); +}; + +test_case test_table[]= +{ + { + "simple string", + test<count_string>::run + }, + { + "flyweight, hashed factory", + test<flyweight<count_string,count_hashed_factory> >::run + }, + { + "flyweight, hashed factory, no tracking", + test<flyweight<count_string,count_hashed_factory,no_tracking> >::run + }, + { + "flyweight, set-based factory", + test<flyweight<count_string,count_set_factory> >::run + }, + { + "flyweight, set-based factory, no tracking", + test<flyweight<count_string,count_set_factory,no_tracking> >::run + } +}; + +const int num_test_cases=sizeof(test_table)/sizeof(test_case); + +int main() +{ + try{ + for(int i=0;i<num_test_cases;++i){ + std::cout<<i+1<<". "<<test_table[i].name<<"\n"; + } + int option=-1; + for(;;){ + std::cout<<"select option, enter to exit: "; + std::string str; + std::getline(std::cin,str); + if(str.empty())std::exit(EXIT_SUCCESS); + std::istringstream istr(str); + istr>>option; + if(option>=1&&option<=num_test_cases){ + --option; /* pass from 1-based menu to 0-based test_table */ + break; + } + } + + std::cout<<"enter file name: "; + std::string file; + std::getline(std::cin,file); + std::size_t result=0; + result=test_table[option].test(file); + } + catch(const std::exception& e){ + std::cout<<"error: "<<e.what()<<"\n"; + } + + return 0; +} |