• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifdef _MSC_VER
12 #pragma warning (disable : 4512)
13 #pragma warning (disable : 4267)
14 #pragma warning (disable : 4244)
15 #endif
16 
17 #define BOOST_CONTAINER_VECTOR_ALLOC_STATS
18 
19 #include <boost/container/allocator.hpp>
20 #include <vector>
21 #include <boost/container/vector.hpp>
22 
23 #include <memory>    //std::allocator
24 #include <iostream>  //std::cout, std::endl
25 #include <cstring>   //std::strcmp
26 #include <boost/timer/timer.hpp>
27 #include <typeinfo>
28 using boost::timer::cpu_timer;
29 using boost::timer::cpu_times;
30 using boost::timer::nanosecond_type;
31 
32 namespace bc = boost::container;
33 
34 #if defined(BOOST_CONTAINER_VECTOR_ALLOC_STATS)
35 
36 template<class T, class Allocator>
reset_alloc_stats(std::vector<T,Allocator> &)37 static void reset_alloc_stats(std::vector<T, Allocator> &)
38    {}
39 
40 template<class T, class Allocator>
get_num_alloc(std::vector<T,Allocator> &)41 static std::size_t get_num_alloc(std::vector<T, Allocator> &)
42    {  return 0;   }
43 
44 template<class T, class Allocator>
get_num_expand(std::vector<T,Allocator> &)45 static std::size_t get_num_expand(std::vector<T, Allocator> &)
46    {  return 0;   }
47 
48 template<class T, class Allocator>
reset_alloc_stats(bc::vector<T,Allocator> & v)49 static void reset_alloc_stats(bc::vector<T, Allocator> &v)
50    { v.reset_alloc_stats(); }
51 
52 template<class T, class Allocator>
get_num_alloc(bc::vector<T,Allocator> & v)53 static std::size_t get_num_alloc(bc::vector<T, Allocator> &v)
54    {  return v.num_alloc;  }
55 
56 template<class T, class Allocator>
get_num_expand(bc::vector<T,Allocator> & v)57 static std::size_t get_num_expand(bc::vector<T, Allocator> &v)
58    {  return v.num_expand_fwd;  }
59 
60 #endif   //BOOST_CONTAINER_VECTOR_ALLOC_STATS
61 
62 class MyInt
63 {
64    int int_;
65 
66    public:
MyInt(int i=0)67    explicit MyInt(int i = 0)
68       : int_(i)
69    {}
70 
MyInt(const MyInt & other)71    MyInt(const MyInt &other)
72       :  int_(other.int_)
73    {}
74 
operator =(const MyInt & other)75    MyInt & operator=(const MyInt &other)
76    {
77       int_ = other.int_;
78       return *this;
79    }
80 
~MyInt()81    ~MyInt()
82    {
83       int_ = 0;
84    }
85 };
86 
87 template<class Container>
vector_test_template(unsigned int num_iterations,unsigned int num_elements)88 void vector_test_template(unsigned int num_iterations, unsigned int num_elements)
89 {
90    unsigned int numalloc = 0, numexpand = 0;
91 
92    cpu_timer timer;
93    timer.resume();
94 
95    unsigned int capacity = 0;
96    for(unsigned int r = 0; r != num_iterations; ++r){
97       Container v;
98       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
99          reset_alloc_stats(v);
100       #endif
101       //v.reserve(num_elements);
102       //MyInt a[3];
103 /*
104       for(unsigned int e = 0; e != num_elements/3; ++e){
105          v.insert(v.end(), &a[0], &a[0]+3);
106       }*/
107 /*
108       for(unsigned int e = 0; e != num_elements/3; ++e){
109          v.insert(v.end(), 3, MyInt(e));
110       }*/
111 /*
112       for(unsigned int e = 0; e != num_elements/3; ++e){
113          v.insert(v.empty() ? v.end() : --v.end(), &a[0], &a[0]+3);
114       }*/
115 /*
116       for(unsigned int e = 0; e != num_elements/3; ++e){
117          v.insert(v.empty() ? v.end() : --v.end(), 3, MyInt(e));
118       }*/
119 /*
120       for(unsigned int e = 0; e != num_elements/3; ++e){
121          v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), &a[0], &a[0]+3);
122       }*/
123 /*
124       for(unsigned int e = 0; e != num_elements/3; ++e){
125          v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), 3, MyInt(e));
126       }*/
127 /*
128       for(unsigned int e = 0; e != num_elements; ++e){
129          v.insert(v.end(), MyInt(e));
130       }*/
131 /*
132       for(unsigned int e = 0; e != num_elements; ++e){
133          v.insert(v.empty() ? v.end() : --v.end(), MyInt(e));
134       }*/
135 
136       for(unsigned int e = 0; e != num_elements; ++e){
137          v.push_back(MyInt(e));
138       }
139 
140       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
141          numalloc  += get_num_alloc(v);
142          numexpand += get_num_expand(v);
143       #endif
144       capacity = static_cast<unsigned int>(v.capacity());
145    }
146 
147    timer.stop();
148    nanosecond_type nseconds = timer.elapsed().wall;
149 
150    std::cout   << std::endl
151                << "Allocator: " << typeid(typename Container::allocator_type).name()
152                << std::endl
153                << "  push_back ns:              "
154                << float(nseconds)/(num_iterations*num_elements)
155                << std::endl
156                << "  capacity  -  alloc calls (new/expand):  "
157                   << (unsigned int)capacity << "  -  "
158                   << (float(numalloc) + float(numexpand))/num_iterations
159                   << "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
160                << std::endl << std::endl;
161    bc::dlmalloc_trim(0);
162 }
163 
print_header()164 void print_header()
165 {
166    std::cout   << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
167                << "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
168                << "New allocations" << ";" << "Fwd expansions" << std::endl;
169 }
170 
main()171 int main()
172 {
173    //#define SINGLE_TEST
174    #define SIMPLE_IT
175    #ifdef SINGLE_TEST
176       #ifdef NDEBUG
177       std::size_t numit [] = { 1000 };
178       #else
179       std::size_t numit [] = { 100 };
180       #endif
181       std::size_t numele [] = { 10000 };
182    #elif defined SIMPLE_IT
183       std::size_t numit [] = { 3 };
184       std::size_t numele [] = { 10000 };
185    #else
186       #ifdef NDEBUG
187       unsigned int numit []  = { 1000, 10000, 100000, 1000000 };
188       #else
189       unsigned int numit []  = { 100, 1000, 10000, 100000 };
190       #endif
191       unsigned int numele [] = { 10000, 1000,   100,     10       };
192    #endif
193 
194    print_header();
195    for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
196       vector_test_template< bc::vector<MyInt, std::allocator<MyInt> > >(numit[i], numele[i]);
197       vector_test_template< bc::vector<MyInt, bc::allocator<MyInt, 1> > >(numit[i], numele[i]);
198       vector_test_template<bc::vector<MyInt, bc::allocator<MyInt, 2, bc::expand_bwd | bc::expand_fwd> > >(numit[i], numele[i]);
199       vector_test_template<bc::vector<MyInt, bc::allocator<MyInt, 2> > >(numit[i], numele[i]);
200    }
201    return 0;
202 }
203