• 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 
21 #undef BOOST_CONTAINER_VECTOR_ALLOC_STATS
22 
23 #include <memory>    //std::allocator
24 #include <iostream>  //std::cout, std::endl
25 #include <cassert>   //assert
26 
27 #include <boost/timer/timer.hpp>
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 typedef std::allocator<int>   StdAllocator;
35 typedef bc::allocator<int, 2> AllocatorPlusV2;
36 typedef bc::allocator<int, 1> AllocatorPlusV1;
37 
38 template<class Allocator> struct get_allocator_name;
39 
40 template<> struct get_allocator_name<StdAllocator>
getget_allocator_name41 {  static const char *get() {  return "StdAllocator";  } };
42 
43 template<> struct get_allocator_name<AllocatorPlusV2>
getget_allocator_name44 {  static const char *get() {  return "AllocatorPlusV2";  } };
45 
46 template<> struct get_allocator_name<AllocatorPlusV1>
getget_allocator_name47 {  static const char *get() {  return "AllocatorPlusV1";  } };
48 
49 class MyInt
50 {
51    std::size_t int_; //Use a type that will grow on 64 bit machines
52 
53    public:
MyInt(int i=0)54    MyInt(int i = 0) : int_(i){}
55 
MyInt(const MyInt & other)56    MyInt(const MyInt &other)
57       :  int_(other.int_)
58    {}
59 
operator =(const MyInt & other)60    MyInt & operator=(const MyInt &other)
61    {
62       int_ = other.int_;
63       return *this;
64    }
65 };
66 
print_header()67 void print_header()
68 {
69    std::cout   << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
70                << "num_shrink" << ";" << "shrink_to_fit(ns)" << std::endl;
71 }
72 
73 template<class Allocator>
vector_test_template(unsigned int num_iterations,unsigned int num_elements,bool csv_output)74 void vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
75 {
76    typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
77 
78    unsigned int capacity = 0;
79    const std::size_t Step = 5;
80    unsigned int num_shrink = 0;
81    (void)capacity;
82 
83    cpu_timer timer;
84    timer.resume();
85 
86    #ifndef NDEBUG
87    typedef bc::dtl::integral_constant
88       <unsigned, bc::dtl::version<Allocator>::value> alloc_version;
89    #endif
90 
91    for(unsigned int r = 0; r != num_iterations; ++r){
92       bc::vector<MyInt, IntAllocator> v(num_elements);
93       v.reset_alloc_stats();
94       num_shrink = 0;
95       for(unsigned int e = num_elements; e != 0; e -= Step){
96          v.erase(v.end() - Step, v.end());
97          v.shrink_to_fit();
98          assert( (alloc_version::value != 2) || (e == Step) || (v.num_shrink > num_shrink) );
99          num_shrink = v.num_shrink;
100       }
101       assert(v.empty());
102       assert(0 == v.capacity());
103    }
104 
105    timer.stop();
106    nanosecond_type nseconds = timer.elapsed().wall;
107 
108    if(csv_output){
109       std::cout   << get_allocator_name<Allocator>::get()
110                   << ";"
111                   << num_iterations
112                   << ";"
113                   << num_elements
114                   << ";"
115                   << num_shrink
116                   << ";"
117                   << float(nseconds)/(num_iterations*num_elements)
118                   << std::endl;
119    }
120    else{
121       std::cout   << std::endl
122                   << "Allocator: " << get_allocator_name<Allocator>::get()
123                   << std::endl
124                   << "  num_shrink:         " << num_shrink
125                   << std::endl
126                   << "  shrink_to_fit ns:   "
127                   << float(nseconds)/(num_iterations*num_elements)
128                   << std::endl << std::endl;
129    }
130    bc::dlmalloc_trim(0);
131 }
132 
main(int argc,const char * argv[])133 int main(int argc, const char *argv[])
134 {
135    //#define SINGLE_TEST
136    #define SIMPLE_IT
137    #ifdef SINGLE_TEST
138       #ifdef NDEBUG
139       unsigned int numit [] =  { 10 };
140       #else
141       unsigned int numit [] =  { 50 };
142       unsigned int numele[] = { 2000 };
143       #endif
144    #elif defined SIMPLE_IT
145       unsigned int numit [] =  { 3 };
146       unsigned int numele[] = { 2000 };
147    #else
148       #ifdef NDEBUG
149       unsigned int numit [] =  { 100,   1000, 10000 };
150       #else
151       unsigned int numit [] =  { 10,   100, 1000 };
152       #endif
153       unsigned int numele [] = { 10000, 2000, 500   };
154    #endif
155 
156    bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
157 
158    if(csv_output){
159       print_header();
160       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
161          vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
162       }
163       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
164          vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
165       }
166       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
167          vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
168       }
169    }
170    else{
171       for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
172          std::cout   << "\n    -----------------------------------    \n"
173                      <<   "  Iterations/Elements:         " << numit[i] << "/" << numele[i]
174                      << "\n    -----------------------------------    \n";
175          vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
176          vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
177          vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
178       }
179    }
180    return 0;
181 }
182