• 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 #endif
14 
15 #include <boost/container/allocator.hpp>
16 
17 #define BOOST_CONTAINER_VECTOR_ALLOC_STATS
18 
19 #include <boost/container/vector.hpp>
20 #include <memory>    //std::allocator
21 #include <iostream>  //std::cout, std::endl
22 #include <cassert>   //assert
23 
24 #include <boost/timer/timer.hpp>
25 using boost::timer::cpu_timer;
26 using boost::timer::cpu_times;
27 using boost::timer::nanosecond_type;
28 
29 namespace bc = boost::container;
30 
31 typedef std::allocator<int>   StdAllocator;
32 typedef bc::allocator<int, 2, bc::expand_bwd | bc::expand_fwd> AllocatorPlusV2Mask;
33 typedef bc::allocator<int, 2, bc::expand_fwd> AllocatorPlusV2;
34 typedef bc::allocator<int, 1> AllocatorPlusV1;
35 
36 template<class Allocator> struct get_allocator_name;
37 
38 template<> struct get_allocator_name<StdAllocator>
getget_allocator_name39 {  static const char *get() {  return "StdAllocator";  } };
40 
41 template<> struct get_allocator_name<AllocatorPlusV2Mask>
getget_allocator_name42 {  static const char *get() {  return "AllocatorPlusV2Mask";  }   };
43 
44 template<> struct get_allocator_name<AllocatorPlusV2>
getget_allocator_name45 {  static const char *get() {  return "AllocatorPlusV2";  } };
46 
47 template<> struct get_allocator_name<AllocatorPlusV1>
getget_allocator_name48 {  static const char *get() {  return "AllocatorPlusV1";  } };
49 
50 //typedef int MyInt;
51 
52 class MyInt
53 {
54    int int_;
55 
56    public:
MyInt(int i=0)57    MyInt(int i = 0)
58       : int_(i)
59    {}
60 
MyInt(const MyInt & other)61    MyInt(const MyInt &other)
62       :  int_(other.int_)
63    {}
64 
operator =(const MyInt & other)65    MyInt & operator=(const MyInt &other)
66    {
67       int_ = other.int_;
68       return *this;
69    }
70 
~MyInt()71    ~MyInt()
72    {
73       int_ = 0;
74    }
75 };
76 namespace boost{
77 
78 template<class T>
79 struct has_trivial_destructor_after_move;
80 
81 template<>
82 struct has_trivial_destructor_after_move<MyInt>
83 {
84    static const bool value = true;
85    //static const bool value = false;
86 };
87 
88 }  //namespace boost{
89 
90 
print_header()91 void print_header()
92 {
93    std::cout   << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
94                << "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
95                << "New allocations" << ";" << "Bwd expansions" << std::endl;
96 }
97 
98 template<class Allocator>
vector_test_template(unsigned int num_iterations,unsigned int num_elements,bool csv_output)99 void vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
100 {
101    typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
102    unsigned int numalloc = 0, numexpand = 0;
103 
104    cpu_timer timer;
105    timer.resume();
106 
107    unsigned int capacity = 0;
108    for(unsigned int r = 0; r != num_iterations; ++r){
109       bc::vector<MyInt, IntAllocator> v;
110       v.reset_alloc_stats();
111       void *first_mem = 0;
112       try{
113          first_mem = bc::dlmalloc_malloc(sizeof(MyInt)*num_elements*3/2);
114          v.push_back(MyInt(0));
115          bc::dlmalloc_free(first_mem);
116 
117          for(unsigned int e = 0; e != num_elements; ++e){
118             v.push_back(MyInt(e));
119          }
120          numalloc  += v.num_alloc;
121          numexpand += v.num_expand_bwd;
122          capacity = static_cast<unsigned int>(v.capacity());
123       }
124       catch(...){
125          bc::dlmalloc_free(first_mem);
126          throw;
127       }
128    }
129 
130    assert(bc::dlmalloc_allocated_memory() == 0);
131 
132    timer.stop();
133    nanosecond_type nseconds = timer.elapsed().wall;
134 
135    if(csv_output){
136       std::cout   << get_allocator_name<Allocator>::get()
137                   << ";"
138                   << num_iterations
139                   << ";"
140                   << num_elements
141                   << ";"
142                   << capacity
143                   << ";"
144                   << float(nseconds)/(num_iterations*num_elements)
145                   << ";"
146                   << (float(numalloc) + float(numexpand))/num_iterations
147                   << ";"
148                   << float(numalloc)/num_iterations
149                   << ";"
150                   << float(numexpand)/num_iterations
151                   << std::endl;
152    }
153    else{
154       std::cout   << std::endl
155                   << "Allocator: " << get_allocator_name<Allocator>::get()
156                   << std::endl
157                   << "  push_back ns:              "
158                   << float(nseconds)/(num_iterations*num_elements)
159                   << std::endl
160                   << "  capacity  -  alloc calls (new/expand):  "
161                      << (unsigned int)capacity << "  -  "
162                      << (float(numalloc) + float(numexpand))/num_iterations
163                      << "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
164                   << std::endl;
165       std::cout   << '\n'
166                   << "    -----------------------------------    "
167                   << std::endl;
168    }
169    bc::dlmalloc_trim(0);
170 }
171 
main(int argc,const char * argv[])172 int main(int argc, const char *argv[])
173 {
174    //#define SINGLE_TEST
175    #define SIMPLE_IT
176    #ifdef SINGLE_TEST
177       #ifdef NDEBUG
178       unsigned int numit [] = { 10 };
179       #else
180       unsigned int numit [] = { 10 };
181       #endif
182       unsigned int numele [] = { 10000 };
183    #elif defined(SIMPLE_IT)
184       unsigned int numit [] = { 3 };
185       unsigned int numele[] = { 10000 };
186    #else
187       #ifdef NDEBUG
188       unsigned int numit [] = { 2000, 20000, 200000, 2000000 };
189       #else
190       unsigned int numit [] = { 100, 1000, 10000, 100000 };
191       #endif
192       unsigned int numele [] = { 10000, 1000,   100,     10       };
193    #endif
194 
195    bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
196 
197    if(csv_output){
198       print_header();
199       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
200          vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
201       }
202       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
203          vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
204       }
205       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
206          vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
207       }
208       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
209          vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
210       }
211    }
212    else{
213       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
214          std::cout   << "\n    -----------------------------------    \n"
215                      <<   "  Iterations/Elements:         " << numit[i] << "/" << numele[i]
216                      << "\n    -----------------------------------    \n";
217          vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
218          vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
219          vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
220          vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
221       }
222    }
223    return 0;
224 }
225