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