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>
27 using boost::move_detail::cpu_timer
;
28 using boost::move_detail::cpu_times
;
29 using boost::move_detail::nanosecond_type
;
42 MyInt(const MyInt
&other
)
46 MyInt
& operator=(const MyInt
&other
)
60 struct has_trivial_destructor_after_move
;
63 struct has_trivial_destructor_after_move
<MyInt
>
65 static const bool value
= true;
66 //static const bool value = false;
72 namespace bc
= boost::container
;
74 typedef std::allocator
<MyInt
> StdAllocator
;
75 typedef bc::allocator
<MyInt
, 2, bc::expand_bwd
| bc::expand_fwd
> AllocatorPlusV2Mask
;
76 typedef bc::allocator
<MyInt
, 2, bc::expand_fwd
> AllocatorPlusV2
;
77 typedef bc::allocator
<MyInt
, 1> AllocatorPlusV1
;
79 template<class Allocator
> struct get_allocator_name
;
81 template<> struct get_allocator_name
<StdAllocator
>
82 { static const char *get() { return "StdAllocator"; } };
84 template<> struct get_allocator_name
<AllocatorPlusV2Mask
>
85 { static const char *get() { return "AllocatorPlusV2Mask"; } };
87 template<> struct get_allocator_name
<AllocatorPlusV2
>
88 { static const char *get() { return "AllocatorPlusV2"; } };
90 template<> struct get_allocator_name
<AllocatorPlusV1
>
91 { static const char *get() { return "AllocatorPlusV1"; } };
98 std::cout
<< "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
99 << "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
100 << "New allocations" << ";" << "Bwd expansions" << std::endl
;
103 template<class Allocator
>
104 void vector_test_template(std::size_t num_iterations
, std::size_t num_elements
, bool csv_output
)
106 typedef Allocator IntAllocator
;
107 std::size_t numalloc
= 0, numexpand
= 0;
112 std::size_t capacity
= 0;
113 for(std::size_t r
= 0; r
!= num_iterations
; ++r
){
114 bc::vector
<MyInt
, IntAllocator
> v
;
115 v
.reset_alloc_stats();
118 first_mem
= bc::dlmalloc_malloc(sizeof(MyInt
)*num_elements
*3/2);
119 v
.push_back(MyInt(0));
120 bc::dlmalloc_free(first_mem
);
122 for(std::size_t e
= 0; e
!= num_elements
; ++e
){
123 v
.push_back(MyInt((int)e
));
125 numalloc
+= v
.num_alloc
;
126 numexpand
+= v
.num_expand_bwd
;
127 capacity
= static_cast<std::size_t>(v
.capacity());
130 bc::dlmalloc_free(first_mem
);
136 assert(bc::dlmalloc_allocated_memory() == 0);
139 nanosecond_type nseconds
= timer
.elapsed().wall
;
142 std::cout
<< get_allocator_name
<Allocator
>::get()
150 << float(nseconds
)/float(num_iterations
*num_elements
)
152 << (float(numalloc
) + float(numexpand
))/float(num_iterations
)
154 << float(numalloc
)/float(num_iterations
)
156 << float(numexpand
)/float(num_iterations
)
160 std::cout
<< std::endl
161 << "Allocator: " << get_allocator_name
<Allocator
>::get()
164 << float(nseconds
)/float(num_iterations
*num_elements
)
166 << " capacity - alloc calls (new/expand): "
167 << (std::size_t)capacity
<< " - "
168 << (float(numalloc
) + float(numexpand
))/float(num_iterations
)
169 << "(" << float(numalloc
)/float(num_iterations
) << "/" << float(numexpand
)/float(num_iterations
) << ")"
172 << " ----------------------------------- "
175 bc::dlmalloc_trim(0);
178 int main(int argc
, const char *argv
[])
180 //#define SINGLE_TEST
184 std::size_t numit
[] = { 10 };
186 std::size_t numit
[] = { 10 };
188 std::size_t numele
[] = { 10000 };
189 #elif defined(SIMPLE_IT)
190 std::size_t numit
[] = { 3 };
191 std::size_t numele
[] = { 10000 };
194 std::size_t numit
[] = { 2000, 20000, 200000, 2000000 };
196 std::size_t numit
[] = { 100, 1000, 10000, 100000 };
198 std::size_t numele
[] = { 10000, 1000, 100, 10 };
201 bool csv_output
= argc
== 2 && (strcmp(argv
[1], "--csv-output") == 0);
205 for(std::size_t i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
206 vector_test_template
<StdAllocator
>(numit
[i
], numele
[i
], csv_output
);
208 for(std::size_t i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
209 vector_test_template
<AllocatorPlusV1
>(numit
[i
], numele
[i
], csv_output
);
211 for(std::size_t i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
212 vector_test_template
<AllocatorPlusV2Mask
>(numit
[i
], numele
[i
], csv_output
);
214 for(std::size_t i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
215 vector_test_template
<AllocatorPlusV2
>(numit
[i
], numele
[i
], csv_output
);
219 for(std::size_t i
= 0; i
< sizeof(numele
)/sizeof(numele
[0]); ++i
){
220 std::cout
<< "\n ----------------------------------- \n"
221 << " Iterations/Elements: " << numit
[i
] << "/" << numele
[i
]
222 << "\n ----------------------------------- \n";
223 vector_test_template
<StdAllocator
>(numit
[i
], numele
[i
], csv_output
);
224 vector_test_template
<AllocatorPlusV1
>(numit
[i
], numele
[i
], csv_output
);
225 vector_test_template
<AllocatorPlusV2Mask
>(numit
[i
], numele
[i
], csv_output
);
226 vector_test_template
<AllocatorPlusV2
>(numit
[i
], numele
[i
], csv_output
);