• 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/detail/dlmalloc.hpp>
16 
17 #define BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
18 
19 #include <iostream>  //std::cout, std::endl
20 #include <typeinfo>  //typeid
21 #include <cassert>   //assert
22 
23 #include <boost/timer/timer.hpp>
24 using boost::timer::cpu_timer;
25 using boost::timer::cpu_times;
26 using boost::timer::nanosecond_type;
27 
28 using namespace boost::container;
29 
30 template <class POD>
allocation_timing_test(unsigned int num_iterations,unsigned int num_elements)31 void allocation_timing_test(unsigned int num_iterations, unsigned int num_elements)
32 {
33    size_t capacity = 0;
34    unsigned int numalloc = 0, numexpand = 0;
35 
36    std::cout
37       << "    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   \n"
38       << "  Iterations/Elements:       " << num_iterations << "/" << num_elements << '\n'
39       << "    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   \n"
40       << std::endl;
41 
42 
43    allocation_type malloc_types[] = { BOOST_CONTAINER_EXPAND_BWD, BOOST_CONTAINER_EXPAND_FWD, BOOST_CONTAINER_ALLOCATE_NEW };
44    const char *    malloc_names[] = { "Backwards expansion", "Forward expansion", "New allocation" };
45    for(size_t i = 0; i < sizeof(malloc_types)/sizeof(allocation_type); ++i){
46       numalloc = 0; numexpand = 0;
47       const allocation_type m_mode = malloc_types[i];
48       const char *malloc_name = malloc_names[i];
49 
50       cpu_timer timer;
51       timer.resume();
52 
53       for(unsigned int r = 0; r != num_iterations; ++r){
54          void *first_mem = 0;
55          if(m_mode != BOOST_CONTAINER_EXPAND_FWD)
56             first_mem = dlmalloc_malloc(sizeof(POD)*num_elements*3/2);
57          void *addr = dlmalloc_malloc(1*sizeof(POD));
58          if(m_mode == BOOST_CONTAINER_EXPAND_FWD)
59             first_mem = dlmalloc_malloc(sizeof(POD)*num_elements*3/2);
60          capacity = dlmalloc_size(addr)/sizeof(POD);
61          dlmalloc_free(first_mem);
62          ++numalloc;
63 
64          try{
65             dlmalloc_command_ret_t ret;
66             for(size_t e = capacity + 1; e < num_elements; ++e){
67                size_t received_size;
68                size_t min = (capacity+1)*sizeof(POD);
69                size_t max = (capacity*3/2)*sizeof(POD);
70                if(min > max)
71                   max = min;
72                ret = dlmalloc_allocation_command
73                   ( m_mode, sizeof(POD)
74                   , min, max, &received_size, addr);
75                if(!ret.first){
76                   std::cout << "(!ret.first)!" << std::endl;
77                   throw int(0);
78                }
79                if(!ret.second){
80                   assert(m_mode == BOOST_CONTAINER_ALLOCATE_NEW);
81                   if(m_mode != BOOST_CONTAINER_ALLOCATE_NEW){
82                      std::cout << "m_mode != BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
83                      return;
84                   }
85                   dlmalloc_free(addr);
86                   addr = ret.first;
87                   ++numalloc;
88                }
89                else{
90                   assert(m_mode != BOOST_CONTAINER_ALLOCATE_NEW);
91                   if(m_mode == BOOST_CONTAINER_ALLOCATE_NEW){
92                      std::cout << "m_mode == BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
93                      return;
94                   }
95                   ++numexpand;
96                }
97                capacity = received_size/sizeof(POD);
98                addr = ret.first;
99                e = capacity + 1;
100             }
101             dlmalloc_free(addr);
102          }
103          catch(...){
104             dlmalloc_free(addr);
105             throw;
106          }
107       }
108 
109       assert( dlmalloc_allocated_memory() == 0);
110       if(dlmalloc_allocated_memory()!= 0){
111          std::cout << "Memory leak!" << std::endl;
112          return;
113       }
114 
115       timer.stop();
116       nanosecond_type nseconds = timer.elapsed().wall;
117 
118       std::cout   << "  Malloc type:               " << malloc_name
119                   << std::endl
120                   << "  allocation ns:             "
121                   << float(nseconds)/(num_iterations*num_elements)
122                   << std::endl
123                   << "  capacity  -  alloc calls (new/expand):  "
124                      << (unsigned int)capacity << "  -  "
125                      << (float(numalloc) + float(numexpand))/num_iterations
126                      << "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
127                   << std::endl << std::endl;
128       dlmalloc_trim(0);
129    }
130 }
131 
132 template<unsigned N>
133 struct char_holder
134 {
135    char ints_[N];
136 };
137 
138 template<class POD>
allocation_loop()139 int allocation_loop()
140 {
141    std::cout   << std::endl
142                << "-------------------------------------------\n"
143                << "-------------------------------------------\n"
144                << "  Type(sizeof):              " << typeid(POD).name() << " (" << sizeof(POD) << ")\n"
145                << "-------------------------------------------\n"
146                << "-------------------------------------------\n"
147                << std::endl;
148 
149    //#define SINGLE_TEST
150    #define SIMPLE_IT
151    #ifdef SINGLE_TEST
152       #ifdef NDEBUG
153       unsigned int numrep [] = { 50000 };
154       #else
155       unsigned int numrep [] = { 5000 };
156       #endif
157       unsigned int numele [] = { 100 };
158    #elif defined(SIMPLE_IT)
159       unsigned int numrep [] = { 3 };
160       unsigned int numele [] = { 100 };
161    #else
162       #ifdef NDEBUG
163       unsigned int numrep [] = { /*10000, */10000, 100000, 1000000 };
164       #else
165       unsigned int numrep [] = { /*10000, */1000, 10000, 100000 };
166       #endif
167       unsigned int numele [] = { /*10000,  */1000,    100,      10 };
168    #endif
169 
170    for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
171       allocation_timing_test<POD>(numrep[i], numele[i]);
172    }
173 
174    return 0;
175 }
176 
main()177 int main()
178 {
179    dlmalloc_mallopt( (-3)//M_MMAP_THRESHOLD
180              , 100*10000000);
181    //allocation_loop<char_holder<4> >();
182    //allocation_loop<char_holder<6> >();
183    allocation_loop<char_holder<8> >();
184    allocation_loop<char_holder<12> >();
185    //allocation_loop<char_holder<14> >();
186    allocation_loop<char_holder<24> >();
187    return 0;
188 }
189