1 //////////////////////////////////////////////////////////////////////////////
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)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
12 #pragma warning (disable : 4512)
15 #include <boost/container/allocator.hpp>
16 #include <boost/core/no_exceptions_support.hpp>
18 #define BOOST_CONTAINER_VECTOR_ALLOC_STATS
20 #include <boost/container/vector.hpp>
21 #include <memory> //std::allocator
22 #include <iostream> //std::cout, std::endl
23 #include <cassert> //assert
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
;
30 namespace bc
= boost::container
;
32 typedef std::allocator
<int> StdAllocator
;
33 typedef bc::allocator
<int, 2, bc::expand_bwd
| bc::expand_fwd
> AllocatorPlusV2Mask
;
34 typedef bc::allocator
<int, 2, bc::expand_fwd
> AllocatorPlusV2
;
35 typedef bc::allocator
<int, 1> AllocatorPlusV1
;
37 template<class Allocator
> struct get_allocator_name
;
39 template<> struct get_allocator_name
<StdAllocator
>
40 { static const char *get() { return "StdAllocator"; } };
42 template<> struct get_allocator_name
<AllocatorPlusV2Mask
>
43 { static const char *get() { return "AllocatorPlusV2Mask"; } };
45 template<> struct get_allocator_name
<AllocatorPlusV2
>
46 { static const char *get() { return "AllocatorPlusV2"; } };
48 template<> struct get_allocator_name
<AllocatorPlusV1
>
49 { static const char *get() { return "AllocatorPlusV1"; } };
62 MyInt(const MyInt
&other
)
66 MyInt
& operator=(const MyInt
&other
)
80 struct has_trivial_destructor_after_move
;
83 struct has_trivial_destructor_after_move
<MyInt
>
85 static const bool value
= true;
86 //static const bool value = false;
94 std::cout
<< "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
95 << "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
96 << "New allocations" << ";" << "Bwd expansions" << std::endl
;
99 template<class Allocator
>
100 void vector_test_template(unsigned int num_iterations
, unsigned int num_elements
, bool csv_output
)
102 typedef typename
Allocator::template rebind
<MyInt
>::other IntAllocator
;
103 unsigned int numalloc
= 0, numexpand
= 0;
108 unsigned int capacity
= 0;
109 for(unsigned int r
= 0; r
!= num_iterations
; ++r
){
110 bc::vector
<MyInt
, IntAllocator
> v
;
111 v
.reset_alloc_stats();
114 first_mem
= bc::dlmalloc_malloc(sizeof(MyInt
)*num_elements
*3/2);
115 v
.push_back(MyInt(0));
116 bc::dlmalloc_free(first_mem
);
118 for(unsigned int e
= 0; e
!= num_elements
; ++e
){
119 v
.push_back(MyInt(e
));
121 numalloc
+= v
.num_alloc
;
122 numexpand
+= v
.num_expand_bwd
;
123 capacity
= static_cast<unsigned int>(v
.capacity());
126 bc::dlmalloc_free(first_mem
);
132 assert(bc::dlmalloc_allocated_memory() == 0);
135 nanosecond_type nseconds
= timer
.elapsed().wall
;
138 std::cout
<< get_allocator_name
<Allocator
>::get()
146 << float(nseconds
)/(num_iterations
*num_elements
)
148 << (float(numalloc
) + float(numexpand
))/num_iterations
150 << float(numalloc
)/num_iterations
152 << float(numexpand
)/num_iterations
156 std::cout
<< std::endl
157 << "Allocator: " << get_allocator_name
<Allocator
>::get()
160 << float(nseconds
)/(num_iterations
*num_elements
)
162 << " capacity - alloc calls (new/expand): "
163 << (unsigned int)capacity
<< " - "
164 << (float(numalloc
) + float(numexpand
))/num_iterations
165 << "(" << float(numalloc
)/num_iterations
<< "/" << float(numexpand
)/num_iterations
<< ")"
168 << " ----------------------------------- "
171 bc::dlmalloc_trim(0);
174 int main(int argc
, const char *argv
[])
176 //#define SINGLE_TEST
180 unsigned int numit
[] = { 10 };
182 unsigned int numit
[] = { 10 };
184 unsigned int numele
[] = { 10000 };
185 #elif defined(SIMPLE_IT)
186 unsigned int numit
[] = { 3 };
187 unsigned int numele
[] = { 10000 };
190 unsigned int numit
[] = { 2000, 20000, 200000, 2000000 };
192 unsigned int numit
[] = { 100, 1000, 10000, 100000 };
194 unsigned int numele
[] = { 10000, 1000, 100, 10 };
197 bool csv_output
= argc
== 2 && (strcmp(argv
[1], "--csv-output") == 0);
201 for(unsigned int i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
202 vector_test_template
<StdAllocator
>(numit
[i
], numele
[i
], csv_output
);
204 for(unsigned int i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
205 vector_test_template
<AllocatorPlusV1
>(numit
[i
], numele
[i
], csv_output
);
207 for(unsigned int i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
208 vector_test_template
<AllocatorPlusV2Mask
>(numit
[i
], numele
[i
], csv_output
);
210 for(unsigned int i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
211 vector_test_template
<AllocatorPlusV2
>(numit
[i
], numele
[i
], csv_output
);
215 for(unsigned int i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
216 std::cout
<< "\n ----------------------------------- \n"
217 << " Iterations/Elements: " << numit
[i
] << "/" << numele
[i
]
218 << "\n ----------------------------------- \n";
219 vector_test_template
<StdAllocator
>(numit
[i
], numele
[i
], csv_output
);
220 vector_test_template
<AllocatorPlusV1
>(numit
[i
], numele
[i
], csv_output
);
221 vector_test_template
<AllocatorPlusV2Mask
>(numit
[i
], numele
[i
], csv_output
);
222 vector_test_template
<AllocatorPlusV2
>(numit
[i
], numele
[i
], csv_output
);