early-access version 3088

This commit is contained in:
pineappleEA
2022-11-05 15:35:56 +01:00
parent 4e4fc25ce3
commit b601909c6d
35519 changed files with 5996896 additions and 860 deletions

View File

@@ -0,0 +1,34 @@
# Boost Container Library Test Jamfile
# (C) Copyright Ion Gaztanaga 2009.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Adapted from John Maddock's TR1 Jamfile.v2
# Copyright John Maddock 2005.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# this rule enumerates through all the sources and invokes
# the run rule for each source, the result is a list of all
# the run rules, which we can pass on to the test_suite rule:
rule test_all
{
local all_rules = ;
for local fileb in [ glob *.cpp ]
{
all_rules += [ run $(fileb) /boost/container//boost_container
: # additional args
: # test-files
: # requirements
] ;
}
return $(all_rules) ;
}
test-suite container_bench : [ test_all r ] ;

View File

@@ -0,0 +1,340 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//Enable checks in debug mode
#ifndef NDEBUG
#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#endif
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4127)
#pragma warning (disable : 4244)
#pragma warning (disable : 4267)
#endif
#include <boost/container/adaptive_pool.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/list.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <vector> //std::vector
#include <cstddef> //std::size_t
#include <cassert> //assert
#include <boost/move/detail/nsec_clock.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 2> AllocatorPlusV2;
typedef bc::allocator<int, 1> AllocatorPlusV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 1> AdPoolAlignOnlyV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 2> AdPoolAlignOnlyV2;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, 2
, 1> AdPool2PercentV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, 2
, 2> AdPool2PercentV2;
typedef bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 1> SimpleSegregatedStorageV1;
typedef bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 2> SimpleSegregatedStorageV2;
//Explicit instantiation
template class bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 2>;
template class bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 2>;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
template<> struct get_allocator_name<AdPoolAlignOnlyV1>
{ static const char *get() { return "AdPoolAlignOnlyV1"; } };
template<> struct get_allocator_name<AdPoolAlignOnlyV2>
{ static const char *get() { return "AdPoolAlignOnlyV2"; } };
template<> struct get_allocator_name<AdPool2PercentV1>
{ static const char *get() { return "AdPool2PercentV1"; } };
template<> struct get_allocator_name<AdPool2PercentV2>
{ static const char *get() { return "AdPool2PercentV2"; } };
template<> struct get_allocator_name<SimpleSegregatedStorageV1>
{ static const char *get() { return "SimpleSegregatedStorageV1"; } };
template<> struct get_allocator_name<SimpleSegregatedStorageV2>
{ static const char *get() { return "SimpleSegregatedStorageV2"; } };
class MyInt
{
std::size_t int_;
public:
explicit MyInt(std::size_t i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
template<class Allocator>
void list_test_template(std::size_t num_iterations, std::size_t num_elements, bool csv_output)
{
typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
nanosecond_type tinsert, terase;
bc::dlmalloc_malloc_stats_t insert_stats, erase_stats;
std::size_t insert_inuse, erase_inuse;
const size_t sizeof_node = 2*sizeof(void*)+sizeof(int);
typedef bc::list<MyInt, IntAllocator> list_t;
typedef typename list_t::iterator iterator_t;
{
cpu_timer timer;
timer.resume();
list_t l;
for(std::size_t r = 0; r != num_iterations; ++r){
l.insert(l.end(), num_elements, MyInt(r));
}
timer.stop();
tinsert = timer.elapsed().wall;
insert_inuse = bc::dlmalloc_in_use_memory();
insert_stats = bc::dlmalloc_malloc_stats();
/*
iterator_t it(l.begin());
iterator_t last(--l.end());
for(std::size_t n_elem = 0, n_max = l.size()/2-1; n_elem != n_max; ++n_elem)
{
l.splice(it++, l, last--);
}
*/
//l.reverse();
//Now preprocess erase ranges
std::vector<iterator_t> ranges_to_erase;
ranges_to_erase.push_back(l.begin());
for(std::size_t r = 0; r != num_iterations; ++r){
iterator_t next_pos(ranges_to_erase[r]);
std::size_t n = num_elements;
while(n--){ ++next_pos; }
ranges_to_erase.push_back(next_pos);
}
//Measure range erasure function
timer.start();
for(std::size_t r = 0; r != num_iterations; ++r){
assert((r+1) < ranges_to_erase.size());
l.erase(ranges_to_erase[r], ranges_to_erase[r+1]);
}
timer.stop();
terase = timer.elapsed().wall;
erase_inuse = bc::dlmalloc_in_use_memory();
erase_stats = bc::dlmalloc_malloc_stats();
}
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< float(tinsert)/float(num_iterations*num_elements)
<< ";"
<< (unsigned int)insert_stats.system_bytes
<< ";"
<< float(insert_stats.system_bytes)/float(num_iterations*num_elements*sizeof_node)*100.0-100.0
<< ";"
<< (unsigned int)insert_inuse
<< ";"
<< (float(insert_inuse)/float(num_iterations*num_elements*sizeof_node)*100.0)-100.0
<< ";";
std::cout << float(terase)/float(num_iterations*num_elements)
<< ";"
<< (unsigned int)erase_stats.system_bytes
<< ";"
<< (unsigned int)erase_inuse
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " allocation/deallocation(ns): " << float(tinsert)/float(num_iterations*num_elements) << '\t' << float(terase)/float(num_iterations*num_elements)
<< std::endl
<< " Sys MB(overh.)/Inuse MB(overh.): " << (float)insert_stats.system_bytes/(1024*1024) << "(" << float(insert_stats.system_bytes)/float(num_iterations*num_elements*sizeof_node)*100.0-100.0 << "%)"
<< " / "
<< (float)insert_inuse/(1024*1024) << "(" << (float(insert_inuse)/float(num_iterations*num_elements*sizeof_node)*100.0)-100.0 << "%)"
<< std::endl
<< " system MB/inuse bytes after: " << (float)erase_stats.system_bytes/(1024*1024) << '\t' << bc::dlmalloc_in_use_memory()
<< std::endl << std::endl;
}
//Release node_allocator cache
typedef boost::container::dtl::shared_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPoolAlignOnlyV2::nodes_per_block> shared_node_pool_t;
boost::container::dtl::singleton_default
<shared_node_pool_t>::instance().purge_blocks();
//Release adaptive_pool cache
typedef boost::container::dtl::shared_adaptive_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPool2PercentV2::nodes_per_block
, AdPool2PercentV2::max_free_blocks
, AdPool2PercentV2::overhead_percent> shared_adaptive_pool_plus_t;
boost::container::dtl::singleton_default
<shared_adaptive_pool_plus_t>::instance().deallocate_free_blocks();
//Release adaptive_pool cache
typedef boost::container::dtl::shared_adaptive_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPool2PercentV2::nodes_per_block
, AdPool2PercentV2::max_free_blocks
, 0u> shared_adaptive_pool_plus_align_only_t;
boost::container::dtl::singleton_default
<shared_adaptive_pool_plus_align_only_t>::instance().deallocate_free_blocks();
//Release dlmalloc memory
bc::dlmalloc_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Insertion time(ns)" << ";"
<< "System bytes" << ";"
<< "System overhead(%)" << ";"
<< "In use bytes" << ";"
<< "In use overhead(%)" << ";"
<< "Erasure time (ns)" << ";"
<< "System bytes after" << ";"
<< "In use bytes after"
<< std::endl;
}
int main(int argc, const char *argv[])
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
std::size_t numrep[] = { 1000 };
#elif defined(NDEBUG)
std::size_t numrep [] = { 15000 };
#else
std::size_t numrep [] = { 1000 };
#endif
std::size_t numele [] = { 100 };
#elif defined(SIMPLE_IT)
std::size_t numrep [] = { 3 };
std::size_t numele [] = { 100 };
#else
#ifdef NDEBUG
std::size_t numrep [] = { 300, 3000, 30000, 300000, 600000, 1500000, 3000000 };
#else
std::size_t numrep [] = { 20, 200, 2000, 20000, 40000, 100000, 200000 };
#endif
std::size_t numele [] = { 10000, 1000, 100, 10, 5, 2, 1 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){/*
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AllocatorPlusV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AllocatorPlusV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPoolAlignOnlyV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPoolAlignOnlyV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPool2PercentV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPool2PercentV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<SimpleSegregatedStorageV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<SimpleSegregatedStorageV2>(numrep[i], numele[i], csv_output);
}*/
}
else{
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numrep[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
list_test_template<AllocatorPlusV1>(numrep[i], numele[i], csv_output);
list_test_template<AllocatorPlusV2>(numrep[i], numele[i], csv_output);
list_test_template<AdPoolAlignOnlyV1>(numrep[i], numele[i], csv_output);
list_test_template<AdPoolAlignOnlyV2>(numrep[i], numele[i], csv_output);
list_test_template<AdPool2PercentV1>(numrep[i], numele[i], csv_output);
list_test_template<AdPool2PercentV2>(numrep[i], numele[i], csv_output);
list_test_template<SimpleSegregatedStorageV1>(numrep[i], numele[i], csv_output);
list_test_template<SimpleSegregatedStorageV2>(numrep[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,190 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/container/throw_exception.hpp>
#define BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
#include <iostream> //std::cout, std::endl
#include <typeinfo> //typeid
#include <cassert> //assert
#include <boost/move/detail/nsec_clock.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
using namespace boost::container;
template <class POD>
void allocation_timing_test(std::size_t num_iterations, std::size_t num_elements)
{
size_t capacity = 0;
std::size_t numalloc = 0, numexpand = 0;
std::cout
<< " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
<< " Iterations/Elements: " << num_iterations << "/" << num_elements << '\n'
<< " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
<< std::endl;
allocation_type malloc_types[] = { BOOST_CONTAINER_EXPAND_BWD, BOOST_CONTAINER_EXPAND_FWD, BOOST_CONTAINER_ALLOCATE_NEW };
const char * malloc_names[] = { "Backwards expansion", "Forward expansion", "New allocation" };
for(size_t i = 0; i < sizeof(malloc_types)/sizeof(allocation_type); ++i){
numalloc = 0; numexpand = 0;
const allocation_type m_mode = malloc_types[i];
const char *malloc_name = malloc_names[i];
cpu_timer timer;
timer.resume();
for(std::size_t r = 0; r != num_iterations; ++r){
void *first_mem = 0;
if(m_mode != BOOST_CONTAINER_EXPAND_FWD)
first_mem = dlmalloc_malloc(sizeof(POD)*num_elements*3/2);
void *addr = dlmalloc_malloc(1*sizeof(POD));
if(m_mode == BOOST_CONTAINER_EXPAND_FWD)
first_mem = dlmalloc_malloc(sizeof(POD)*num_elements*3/2);
capacity = dlmalloc_size(addr)/sizeof(POD);
dlmalloc_free(first_mem);
++numalloc;
BOOST_TRY{
dlmalloc_command_ret_t ret;
for(size_t e = capacity + 1; e < num_elements; ++e){
size_t received_size;
size_t min = (capacity+1)*sizeof(POD);
size_t max = (capacity*3/2)*sizeof(POD);
if(min > max)
max = min;
ret = dlmalloc_allocation_command
( m_mode, sizeof(POD)
, min, max, &received_size, addr);
if(!ret.first){
throw_runtime_error("!ret.first)");
}
if(!ret.second){
assert(m_mode == BOOST_CONTAINER_ALLOCATE_NEW);
if(m_mode != BOOST_CONTAINER_ALLOCATE_NEW){
std::cout << "m_mode != BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
return;
}
dlmalloc_free(addr);
addr = ret.first;
++numalloc;
}
else{
assert(m_mode != BOOST_CONTAINER_ALLOCATE_NEW);
if(m_mode == BOOST_CONTAINER_ALLOCATE_NEW){
std::cout << "m_mode == BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
return;
}
++numexpand;
}
capacity = received_size/sizeof(POD);
addr = ret.first;
e = capacity + 1;
}
dlmalloc_free(addr);
}
BOOST_CATCH(...){
dlmalloc_free(addr);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
assert( dlmalloc_allocated_memory() == 0);
if(dlmalloc_allocated_memory()!= 0){
std::cout << "Memory leak!" << std::endl;
return;
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
std::cout << " Malloc type: " << malloc_name
<< std::endl
<< " allocation ns: "
<< float(nseconds)/float(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (std::size_t)capacity << " - "
<< (float(numalloc) + float(numexpand))/float(num_iterations)
<< "(" << float(numalloc)/float(num_iterations) << "/" << float(numexpand)/float(num_iterations) << ")"
<< std::endl << std::endl;
dlmalloc_trim(0);
}
}
template<unsigned N>
struct char_holder
{
char ints_[N];
};
template<class POD>
int allocation_loop()
{
std::cout << std::endl
<< "-------------------------------------------\n"
<< "-------------------------------------------\n"
<< " Type(sizeof): " << typeid(POD).name() << " (" << sizeof(POD) << ")\n"
<< "-------------------------------------------\n"
<< "-------------------------------------------\n"
<< std::endl;
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numrep [] = { 50000 };
#else
std::size_t numrep [] = { 5000 };
#endif
std::size_t numele [] = { 100 };
#elif defined(SIMPLE_IT)
std::size_t numrep [] = { 3 };
std::size_t numele [] = { 100 };
#else
#ifdef NDEBUG
std::size_t numrep [] = { /*10000, */10000, 100000, 1000000 };
#else
std::size_t numrep [] = { /*10000, */1000, 10000, 100000 };
#endif
std::size_t numele [] = { /*10000, */1000, 100, 10 };
#endif
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
allocation_timing_test<POD>(numrep[i], numele[i]);
}
return 0;
}
int main()
{
dlmalloc_mallopt( (-3)//M_MMAP_THRESHOLD
, 100*10000000);
//allocation_loop<char_holder<4> >();
//allocation_loop<char_holder<6> >();
allocation_loop<char_holder<8> >();
allocation_loop<char_holder<12> >();
//allocation_loop<char_holder<14> >();
allocation_loop<char_holder<24> >();
return 0;
}

View File

@@ -0,0 +1,230 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/allocator.hpp>
#include <boost/core/no_exceptions_support.hpp>
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/vector.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <cassert> //assert
#include <boost/move/detail/nsec_clock.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
//typedef int MyInt;
class MyInt
{
int int_;
public:
MyInt(int i = 0)
: int_(i)
{}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
~MyInt()
{
int_ = 0;
}
};
namespace boost{
template<class T>
struct has_trivial_destructor_after_move;
template<>
struct has_trivial_destructor_after_move<MyInt>
{
static const bool value = true;
//static const bool value = false;
};
} //namespace boost{
namespace bc = boost::container;
typedef std::allocator<MyInt> StdAllocator;
typedef bc::allocator<MyInt, 2, bc::expand_bwd | bc::expand_fwd> AllocatorPlusV2Mask;
typedef bc::allocator<MyInt, 2, bc::expand_fwd> AllocatorPlusV2;
typedef bc::allocator<MyInt, 1> AllocatorPlusV1;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2Mask>
{ static const char *get() { return "AllocatorPlusV2Mask"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
<< "New allocations" << ";" << "Bwd expansions" << std::endl;
}
template<class Allocator>
void vector_test_template(std::size_t num_iterations, std::size_t num_elements, bool csv_output)
{
typedef Allocator IntAllocator;
std::size_t numalloc = 0, numexpand = 0;
cpu_timer timer;
timer.resume();
std::size_t capacity = 0;
for(std::size_t r = 0; r != num_iterations; ++r){
bc::vector<MyInt, IntAllocator> v;
v.reset_alloc_stats();
void *first_mem = 0;
BOOST_TRY{
first_mem = bc::dlmalloc_malloc(sizeof(MyInt)*num_elements*3/2);
v.push_back(MyInt(0));
bc::dlmalloc_free(first_mem);
for(std::size_t e = 0; e != num_elements; ++e){
v.push_back(MyInt((int)e));
}
numalloc += v.num_alloc;
numexpand += v.num_expand_bwd;
capacity = static_cast<std::size_t>(v.capacity());
}
BOOST_CATCH(...){
bc::dlmalloc_free(first_mem);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
assert(bc::dlmalloc_allocated_memory() == 0);
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< capacity
<< ";"
<< float(nseconds)/float(num_iterations*num_elements)
<< ";"
<< (float(numalloc) + float(numexpand))/float(num_iterations)
<< ";"
<< float(numalloc)/float(num_iterations)
<< ";"
<< float(numexpand)/float(num_iterations)
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " push_back ns: "
<< float(nseconds)/float(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (std::size_t)capacity << " - "
<< (float(numalloc) + float(numexpand))/float(num_iterations)
<< "(" << float(numalloc)/float(num_iterations) << "/" << float(numexpand)/float(num_iterations) << ")"
<< std::endl;
std::cout << '\n'
<< " ----------------------------------- "
<< std::endl;
}
bc::dlmalloc_trim(0);
}
int main(int argc, const char *argv[])
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numit [] = { 10 };
#else
std::size_t numit [] = { 10 };
#endif
std::size_t numele [] = { 10000 };
#elif defined(SIMPLE_IT)
std::size_t numit [] = { 3 };
std::size_t numele[] = { 10000 };
#else
#ifdef NDEBUG
std::size_t numit [] = { 2000, 20000, 200000, 2000000 };
#else
std::size_t numit [] = { 100, 1000, 10000, 100000 };
#endif
std::size_t numele [] = { 10000, 1000, 100, 10 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
else{
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,202 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4267)
#pragma warning (disable : 4244)
#endif
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/allocator.hpp>
#include <vector>
#include <boost/container/vector.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <cstring> //std::strcmp
#include <boost/move/detail/nsec_clock.hpp>
#include <typeinfo>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
namespace bc = boost::container;
#if defined(BOOST_CONTAINER_VECTOR_ALLOC_STATS)
template<class T, class Allocator>
static void reset_alloc_stats(std::vector<T, Allocator> &)
{}
template<class T, class Allocator>
static std::size_t get_num_alloc(std::vector<T, Allocator> &)
{ return 0; }
template<class T, class Allocator>
static std::size_t get_num_expand(std::vector<T, Allocator> &)
{ return 0; }
template<class T, class Allocator>
static void reset_alloc_stats(bc::vector<T, Allocator> &v)
{ v.reset_alloc_stats(); }
template<class T, class Allocator>
static std::size_t get_num_alloc(bc::vector<T, Allocator> &v)
{ return v.num_alloc; }
template<class T, class Allocator>
static std::size_t get_num_expand(bc::vector<T, Allocator> &v)
{ return v.num_expand_fwd; }
#endif //BOOST_CONTAINER_VECTOR_ALLOC_STATS
class MyInt
{
int int_;
public:
explicit MyInt(int i = 0)
: int_(i)
{}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
~MyInt()
{
int_ = 0;
}
};
template<class Container>
void vector_test_template(std::size_t num_iterations, std::size_t num_elements)
{
std::size_t numalloc = 0, numexpand = 0;
cpu_timer timer;
timer.resume();
std::size_t capacity = 0;
for(std::size_t r = 0; r != num_iterations; ++r){
Container v;
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
reset_alloc_stats(v);
#endif
//v.reserve(num_elements);
//MyInt a[3];
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.end(), &a[0], &a[0]+3);
}*/
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.end(), 3, MyInt((int)e));
}*/
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.empty() ? v.end() : --v.end(), &a[0], &a[0]+3);
}*/
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.empty() ? v.end() : --v.end(), 3, MyInt((int)e));
}*/
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), &a[0], &a[0]+3);
}*/
/*
for(std::size_t e = 0; e != num_elements/3; ++e){
v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), 3, MyInt((int)e));
}*/
/*
for(std::size_t e = 0; e != num_elements; ++e){
v.insert(v.end(), MyInt((int)e));
}*/
/*
for(std::size_t e = 0; e != num_elements; ++e){
v.insert(v.empty() ? v.end() : --v.end(), MyInt((int)e));
}*/
for(std::size_t e = 0; e != num_elements; ++e){
v.push_back(MyInt((int)e));
}
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
numalloc += get_num_alloc(v);
numexpand += get_num_expand(v);
#endif
capacity = static_cast<std::size_t>(v.capacity());
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
std::cout << std::endl
<< "Allocator: " << typeid(typename Container::allocator_type).name()
<< std::endl
<< " push_back ns: "
<< float(nseconds)/float(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (std::size_t)capacity << " - "
<< (float(numalloc) + float(numexpand))/float(num_iterations)
<< "(" << float(numalloc)/float(num_iterations) << "/" << float(numexpand)/float(num_iterations) << ")"
<< std::endl << std::endl;
bc::dlmalloc_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
<< "New allocations" << ";" << "Fwd expansions" << std::endl;
}
int main()
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numit [] = { 1000 };
#else
std::size_t numit [] = { 100 };
#endif
std::size_t numele [] = { 10000 };
#elif defined SIMPLE_IT
std::size_t numit [] = { 3 };
std::size_t numele [] = { 10000 };
#else
#ifdef NDEBUG
std::size_t numit [] = { 1000, 10000, 100000, 1000000 };
#else
std::size_t numit [] = { 100, 1000, 10000, 100000 };
#endif
std::size_t numele [] = { 10000, 1000, 100, 10 };
#endif
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template< bc::vector<MyInt, std::allocator<MyInt> > >(numit[i], numele[i]);
vector_test_template< bc::vector<MyInt, bc::allocator<MyInt, 1> > >(numit[i], numele[i]);
vector_test_template<bc::vector<MyInt, bc::allocator<MyInt, 2, bc::expand_bwd | bc::expand_fwd> > >(numit[i], numele[i]);
vector_test_template<bc::vector<MyInt, bc::allocator<MyInt, 2> > >(numit[i], numele[i]);
}
return 0;
}

View File

@@ -0,0 +1,181 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/allocator.hpp>
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/vector.hpp>
#undef BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <cassert> //assert
#include <boost/move/detail/nsec_clock.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
namespace bc = boost::container;
class MyInt
{
std::ptrdiff_t int_; //Use a type that will grow on 64 bit machines
public:
MyInt(int i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
typedef std::allocator<MyInt> StdAllocator;
typedef bc::allocator<MyInt, 2> AllocatorPlusV2;
typedef bc::allocator<MyInt, 1> AllocatorPlusV1;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "num_shrink" << ";" << "shrink_to_fit(ns)" << std::endl;
}
template<class Allocator>
void vector_test_template(std::size_t num_iterations, std::size_t num_elements, bool csv_output)
{
typedef Allocator IntAllocator;
std::size_t capacity = 0;
const std::size_t Step = 5;
std::size_t num_shrink = 0;
(void)capacity;
cpu_timer timer;
timer.resume();
#ifndef NDEBUG
typedef bc::dtl::integral_constant
<unsigned, bc::dtl::version<Allocator>::value> alloc_version;
#endif
for(std::size_t r = 0; r != num_iterations; ++r){
bc::vector<MyInt, IntAllocator> v(num_elements);
v.reset_alloc_stats();
num_shrink = 0;
for(std::size_t e = num_elements; e != 0; e -= Step){
v.erase(v.end() - std::ptrdiff_t(Step), v.end());
v.shrink_to_fit();
assert( (alloc_version::value != 2) || (e == Step) || (v.num_shrink > num_shrink) );
num_shrink = v.num_shrink;
}
assert(v.empty());
assert(0 == v.capacity());
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< num_shrink
<< ";"
<< float(nseconds)/float(num_iterations*num_elements)
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " num_shrink: " << num_shrink
<< std::endl
<< " shrink_to_fit ns: "
<< float(nseconds)/float(num_iterations*num_elements)
<< std::endl << std::endl;
}
bc::dlmalloc_trim(0);
}
int main(int argc, const char *argv[])
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numit [] = { 10 };
#else
std::size_t numit [] = { 50 };
std::size_t numele[] = { 2000 };
#endif
#elif defined SIMPLE_IT
std::size_t numit [] = { 3 };
std::size_t numele[] = { 2000 };
#else
#ifdef NDEBUG
std::size_t numit [] = { 100, 1000, 10000 };
#else
std::size_t numit [] = { 10, 100, 1000 };
#endif
std::size_t numele [] = { 10000, 2000, 500 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
else{
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,293 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4541)
#pragma warning (disable : 4673)
#pragma warning (disable : 4671)
#pragma warning (disable : 4244)
#endif
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <vector> //std::vector
#include <cstddef> //std::size_t
#include <cassert> //assert
#include <boost/container/allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/vector.hpp>
#include <boost/move/detail/nsec_clock.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
namespace bc = boost::container;
class MyInt
{
int int_;
public:
MyInt(int i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
typedef std::allocator<MyInt> StdAllocator;
typedef bc::allocator<MyInt, 1> AllocatorPlusV1;
typedef bc::allocator<MyInt, 2> AllocatorPlusV2;
typedef bc::adaptive_pool
< MyInt
, bc::ADP_nodes_per_block
, 0//bc::ADP_max_free_blocks
, 2
, 2> AdPool2PercentV2;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AdPool2PercentV2>
{ static const char *get() { return "AdPool2PercentV2"; } };
template<class Allocator>
struct get_vector
{
typedef bc::vector<MyInt, Allocator> type;
static const char *vector_name()
{
return "vector<MyInt>";
}
};
template<class Allocator>
struct get_stable_vector
{
typedef bc::stable_vector
<MyInt, Allocator> type;
static const char *vector_name()
{
return "stable_vector<MyInt>";
}
};
template<template<class> class GetContainer, class Allocator>
void stable_vector_test_template(std::size_t num_iterations, std::size_t num_elements, bool csv_output)
{
typedef typename GetContainer<Allocator>::type vector_type;
//std::size_t top_capacity = 0;
nanosecond_type nseconds;
{
{
vector_type l;
cpu_timer timer;
timer.resume();
for(std::size_t r = 0; r != num_iterations; ++r){
l.insert(l.end(), num_elements, MyInt((int)r));
}
timer.stop();
nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< GetContainer<Allocator>::vector_name()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< float(nseconds)/float(num_iterations*num_elements)
<< ";";
}
else{
std::cout << "Allocator: " << get_allocator_name<Allocator>::get()
<< '\t'
<< GetContainer<Allocator>::vector_name()
<< std::endl
<< " allocation ns: "
<< float(nseconds)/float(num_iterations*num_elements);
}
// top_capacity = l.capacity();
//Now preprocess ranges to erase
std::vector<typename vector_type::iterator> ranges_to_erase;
ranges_to_erase.push_back(l.begin());
for(std::size_t r = 0; r != num_iterations; ++r){
typename vector_type::iterator next_pos(ranges_to_erase[r]);
std::size_t n = num_elements;
while(n--){ ++next_pos; }
ranges_to_erase.push_back(next_pos);
}
//Measure range erasure function
timer.stop();
timer.start();
for(std::size_t r = 0; r != num_iterations; ++r){
std::size_t init_pos = (num_iterations-1)-r;
l.erase(ranges_to_erase[init_pos], l.end());
}
timer.stop();
nseconds = timer.elapsed().wall;
assert(l.empty());
}
}
if(csv_output){
std::cout << float(nseconds)/float(num_iterations*num_elements)
<< std::endl;
}
else{
std::cout << '\t'
<< " deallocation ns: "
<< float(nseconds)/float(num_iterations*num_elements)/*
<< std::endl
<< " max capacity: "
<< static_cast<std::size_t>(top_capacity)
<< std::endl
<< " remaining cap. "
<< static_cast<std::size_t>(top_capacity - num_iterations*num_elements)
<< " (" << (float(top_capacity)/float(num_iterations*num_elements) - 1)*100 << " %)"*/
<< std::endl << std::endl;
}
assert(bc::dlmalloc_all_deallocated());
bc::dlmalloc_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Insertion time(ns)" << ";" << "Erasure time(ns)" << ";"
<< std::endl;
}
void stable_vector_operations()
{
{
bc::stable_vector<int> a(bc::stable_vector<int>::size_type(5), 4);
bc::stable_vector<int> b(a);
bc::stable_vector<int> c(a.cbegin(), a.cend());
b.insert(b.cend(), 0);
c.pop_back();
a.assign(b.cbegin(), b.cend());
a.assign(c.cbegin(), c.cend());
a.assign(1, 2);
}
{
typedef bc::stable_vector<int, std::allocator<int> > stable_vector_t;
stable_vector_t a(bc::stable_vector<int>::size_type(5), 4);
stable_vector_t b(a);
stable_vector_t c(a.cbegin(), a.cend());
b.insert(b.cend(), 0);
c.pop_back();
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(b.cbegin(), b.cend());
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(c.cbegin(), c.cend());
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(1, 2);
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.reserve(100);
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
}
}
int main(int argc, const char *argv[])
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numit [] = { 40 };
#else
std::size_t numit [] = { 4 };
#endif
std::size_t numele [] = { 10000 };
#elif defined(SIMPLE_IT)
std::size_t numit [] = { 3 };
std::size_t numele [] = { 10000 };
#else
#ifdef NDEBUG
std::size_t numit [] = { 40, 400, 4000, 40000 };
#else
std::size_t numit [] = { 4, 40, 400, 4000 };
#endif
std::size_t numele [] = { 10000, 1000, 100, 10 };
#endif
//Warning: range erasure is buggy. Vector iterators are not stable, so it is not
//possible to cache iterators, but indexes!!!
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, StdAllocator>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, StdAllocator>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
}
else{
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
stable_vector_test_template<get_stable_vector, StdAllocator>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, StdAllocator>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/flat_set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//flat_set vs set
launch_tests< flat_multiset<int> , multiset<int> >
("flat_multiset<int>", "multiset<int>");
launch_tests< flat_multiset<string> , multiset<string> >
("flat_multiset<string>", "multiset<string>");
return 0;
}

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/flat_set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//flat_set vs set
launch_tests< flat_set<int> , set<int> >
("flat_set<int>", "set<int>");
launch_tests< flat_set<string> , set<string> >
("flat_set<string>", "set<string>");
return 0;
}

View File

@@ -0,0 +1,35 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include <set>
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set vs std::set
launch_tests< set<int> , std::set<int> >
("set<int>", "std::set<int>");
launch_tests< set<string> , std::set<string> >
("set<string>", "std::set<string>");
//set(sizeopt) vs set(!sizeopt)
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< optimize_size<false> >::type > >
("set<int>(sizeopt=true)", "set<int>(sizeopt=false)");
launch_tests< set<string>, set<string, std::less<string>, std::allocator<string>, tree_assoc_options< optimize_size<false> >::type > >
("set<string>(sizeopt=true)", "set<string>(sizeopt=false)");
return 0;
}

View File

@@ -0,0 +1,483 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP
#define BOOST_CONTAINER_BENCH_BENCH_SET_HPP
#include <iostream>
#include <boost/move/detail/nsec_clock.hpp>
#include <algorithm> //sort
#include <exception>
#include <sstream>
#include <iomanip>
#include <boost/container/vector.hpp>
#include <boost/container/string.hpp>
#include <boost/core/no_exceptions_support.hpp>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
#define SIMPLE_IT
#ifdef SIMPLE_IT
static const std::size_t NIter = 3;
#else
#ifdef NDEBUG
static const std::size_t NIter = 250;
#else
static const std::size_t NIter = 25;
#endif
#endif
static const std::size_t NElements = 1000;
void compare_times(cpu_times time_numerator, cpu_times time_denominator)
{
std::cout << ((double)time_numerator.wall/(double)time_denominator.wall) << '\n' << std::endl;
}
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last )
{
typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
difference_type n = last - first;
for (difference_type i = n-1; i > 0; --i) {
difference_type j = std::rand() % (i+1);
if(j != i) {
boost::adl_move_swap(first[i], first[j]);
}
}
}
boost::container::vector<int> sorted_unique_range_int;
boost::container::vector<int> sorted_range_int;
boost::container::vector<int> random_unique_range_int;
boost::container::vector<int> random_range_int;
void fill_range_ints()
{
//sorted_unique_range_int
sorted_unique_range_int.resize(NElements);
for(std::size_t i = 0, max = sorted_unique_range_int.size(); i != max; ++i){
sorted_unique_range_int[i] = static_cast<int>(i);
}
//sorted_range_int
sorted_range_int = sorted_unique_range_int;
sorted_range_int.insert(sorted_range_int.end(), sorted_unique_range_int.begin(), sorted_unique_range_int.end());
std::sort(sorted_range_int.begin(), sorted_range_int.end());
//random_range_int
std::srand(0);
random_range_int.assign(sorted_range_int.begin(), sorted_range_int.end());
::random_shuffle(random_range_int.begin(), random_range_int.end());
//random_unique_range_int
std::srand(0);
random_unique_range_int.assign(sorted_unique_range_int.begin(), sorted_unique_range_int.end());
::random_shuffle(random_unique_range_int.begin(), random_unique_range_int.end());
}
boost::container::vector<boost::container::string> sorted_unique_range_string;
boost::container::vector<boost::container::string> sorted_range_string;
boost::container::vector<boost::container::string> random_unique_range_string;
boost::container::vector<boost::container::string> random_range_string;
void fill_range_strings()
{
boost::container::string model_s;
model_s.append(sizeof(boost::container::string), '*');
//sorted_unique_range_int
sorted_unique_range_string.resize(NElements);
std::stringstream sstr;
for(std::size_t i = 0, max = sorted_unique_range_string.size(); i != max; ++i){
sstr.str(std::string());
sstr << std::setfill('0') << std::setw(10) << i;
sorted_unique_range_string[i] = model_s;
const std::string &s = sstr.str();
sorted_unique_range_string[i].append(s.begin(), s.end());
}
//sorted_range_string
sorted_range_string = sorted_unique_range_string;
sorted_range_string.insert(sorted_range_string.end(), sorted_unique_range_string.begin(), sorted_unique_range_string.end());
std::sort(sorted_range_string.begin(), sorted_range_string.end());
//random_range_string
std::srand(0);
random_range_string.assign(sorted_range_string.begin(), sorted_range_string.end());
::random_shuffle(random_range_string.begin(), random_range_string.end());
//random_unique_range_string
std::srand(0);
random_unique_range_string.assign(sorted_unique_range_string.begin(), sorted_unique_range_string.end());
::random_shuffle(random_unique_range_string.begin(), random_unique_range_string.end());
}
template<class T>
struct range_provider;
template<>
struct range_provider<int>
{
typedef boost::container::vector<int> type;
static type &sorted_unique()
{ return sorted_unique_range_int; }
static type &sorted()
{ return sorted_range_int; }
static type &random_unique()
{ return random_unique_range_int; }
static type &random()
{ return random_range_int; }
};
template<>
struct range_provider<boost::container::string>
{
typedef boost::container::vector<boost::container::string> type;
static type &sorted_unique()
{ return sorted_unique_range_string; }
static type &sorted()
{ return sorted_range_string; }
static type &random_unique()
{ return random_unique_range_string; }
static type &random()
{ return random_range_string; }
};
template<typename C>
cpu_times copy_destroy_time(boost::container::vector<typename C::value_type> &unique_range)
{
cpu_timer copy_timer, assign_timer, destroy_timer;
cpu_timer total_time;
for(std::size_t i = 0; i != NIter; ++i){
{
C c(unique_range.begin(), unique_range.end());
total_time.resume();
copy_timer.resume();
C caux(c);
copy_timer.stop();
assign_timer.resume();
c = caux;
assign_timer.stop();
destroy_timer.resume();
}
destroy_timer.stop();
total_time.stop();
}
total_time.stop();
std::cout << " Copy sorted range " << double(copy_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Assign sorted range " << double(assign_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Destroy " << double(destroy_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Total time = " << double(total_time.elapsed().wall)/double(1000000000) << "s\n";
return total_time.elapsed();
}
template<typename C>
cpu_times construct_time( boost::container::vector<typename C::value_type> &unique_range
, boost::container::vector<typename C::value_type> &range
, const char *RangeType)
{
cpu_timer sur_timer, sr_timer;
cpu_timer total_time;
for(std::size_t i = 0; i != NIter; ++i){
{
sur_timer.resume();
total_time.resume();
C c(unique_range.begin(), unique_range.end());
sur_timer.stop();
total_time.stop();
}
{
total_time.resume();
sr_timer.resume();
C c(range.begin(), range.end());
sr_timer.stop();
total_time.stop();
}
}
std::cout << " Construct " << RangeType << " unique_range " << double(sur_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Construct " << RangeType << " range " << double(sr_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Total time = " << double(total_time.elapsed().wall)/double(1000000000) << "s\n";
return total_time.elapsed();
}
template<typename C>
cpu_times insert_time( boost::container::vector<typename C::value_type> &unique_range
, boost::container::vector<typename C::value_type> &range
, const char *RangeType)
{
cpu_timer ur_timer,r_timer;
ur_timer.stop();r_timer.stop();
cpu_timer total_time;
total_time.resume();
for(std::size_t i = 0; i != NIter; ++i){
{
total_time.resume();
ur_timer.resume();
C c;
c.insert(unique_range.begin(), unique_range.end());
ur_timer.stop();
total_time.stop();
}
{
total_time.resume();
r_timer.resume();
C c;
c.insert(range.begin(), range.end());
r_timer.stop();
total_time.stop();
}
}
std::cout << " Insert " << RangeType << " unique_range " << double(ur_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Insert " << RangeType << " range " << double(r_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Total time = " << double(total_time.elapsed().wall)/double(1000000000) << "s\n";
return total_time.elapsed();
}
template<typename Iterator>
bool check_not_end(boost::container::vector<Iterator> &iterators, Iterator itend, std::size_t number_of_ends = 0)
{
std::size_t end_count = 0;
for(std::size_t i = 0, max = iterators.size(); i != max; ++i){
if(iterators[i] == itend && (++end_count > number_of_ends) )
return false;
}
return true;
}
template<typename Iterator>
bool check_all_not_empty(boost::container::vector< std::pair<Iterator, Iterator > > &iterator_pairs)
{
for(std::size_t i = 0, max = iterator_pairs.size(); i != max; ++i){
if(iterator_pairs[i].first == iterator_pairs[i].second)
return false;
}
return true;
}
template<typename C>
cpu_times search_time(boost::container::vector<typename C::value_type> &unique_range, const char *RangeType)
{
cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer;
C c(unique_range.begin(), unique_range.end());
cpu_timer total_time;
total_time.resume();
boost::container::vector<typename C::iterator> v_it(NElements);
boost::container::vector< std::pair<typename C::iterator, typename C::iterator> > v_itp(NElements);
for(std::size_t i = 0; i != NIter; ++i){
//Find
{
find_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
v_it[j] = c.find(unique_range[j]);
}
find_timer.stop();
if(!check_not_end(v_it, c.end())){
std::cout << "ERROR! find all elements not found" << std::endl;
}
}
//Lower
{
lower_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
v_it[j] = c.lower_bound(unique_range[j]);
}
lower_timer.stop();
if(!check_not_end(v_it, c.end())){
std::cout << "ERROR! lower_bound all elements not found" << std::endl;
}
}
//Upper
{
upper_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
v_it[j] = c.upper_bound(unique_range[j]);
}
upper_timer.stop();
if(!check_not_end(v_it, c.end(), 1u)){
std::cout << "ERROR! upper_bound all elements not found" << std::endl;
}
}
//Equal
{
equal_range_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
v_itp[j] = c.equal_range(unique_range[j]);
}
equal_range_timer.stop();
if(!check_all_not_empty(v_itp)){
std::cout << "ERROR! equal_range all elements not found" << std::endl;
}
}
//Count
{
std::size_t count = 0;
count_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t j = 0, max = unique_range.size(); j != max; ++j){
count += c.count(unique_range[j]);
}
count_timer.stop();
if(count/2 != c.size()){
std::cout << "ERROR! count all elements not found" << std::endl;
}
}
}
total_time.stop();
std::cout << " Find " << RangeType << " " << double(find_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Lower Bound " << RangeType << " " << double(lower_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Upper Bound " << RangeType << " " << double(upper_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Equal Range " << RangeType << " " << double(equal_range_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Count " << RangeType << " " << double(count_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Total time = " << double(total_time.elapsed().wall)/double(1000000000) << "s\n";
return total_time.elapsed();
}
template<typename C>
void extensions_time(boost::container::vector<typename C::value_type> &sorted_unique_range)
{
cpu_timer sur_timer,sur_opt_timer;
sur_timer.stop();sur_opt_timer.stop();
for(std::size_t i = 0; i != NIter; ++i){
{
sur_timer.resume();
C c(sorted_unique_range.begin(), sorted_unique_range.end());
sur_timer.stop();
}
{
sur_opt_timer.resume();
C c(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end());
sur_opt_timer.stop();
}
}
std::cout << " Construct sorted_unique_range " << double(sur_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Construct sorted_unique_range (extension) " << double(sur_opt_timer.elapsed().wall)/double(1000000000) << "s\n";
std::cout << "Extension/Standard: ";
compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed());
}
template<class BoostClass, class StdClass>
void launch_tests(const char *BoostContName, const char *StdContName)
{
typedef range_provider<typename BoostClass::value_type> get_range_t;
std::cout << std::fixed << std::setw( 11 );
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n';
std::cout << '\n';
std::cout << BoostContName << " .VS " << StdContName << '\n';
std::cout << '\n';
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n' << std::endl;
{
std::cout << "Copy/Assign/Destroy benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = copy_destroy_time< BoostClass >(get_range_t::sorted_unique());
std::cout << "Copy/Assign/Destroy benchmark:" << StdContName << std::endl;
cpu_times std_set_time = copy_destroy_time< StdClass >(get_range_t::sorted_unique());
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered construct benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << "Ordered construct benchmark:" << StdContName << std::endl;
cpu_times std_set_time = construct_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");;
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random construct benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << "Random construct benchmark:" << StdContName << std::endl;
cpu_times std_set_time = construct_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");;
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered Insert benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << "Ordered Insert benchmark:" << StdContName << std::endl;
cpu_times std_set_time = insert_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random Insert benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << "Random Insert benchmark:" << StdContName << std::endl;
cpu_times std_set_time = insert_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered Search benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = search_time< BoostClass >(get_range_t::sorted_unique(), "(ord)");
std::cout << "Ordered Search benchmark:" << StdContName << std::endl;
cpu_times std_set_time = search_time< StdClass >(get_range_t::sorted_unique(), "(ord)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random Search benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = search_time< BoostClass >(get_range_t::random_unique(), "(rnd)");
std::cout << "Random Search benchmark:" << StdContName << std::endl;
cpu_times std_set_time = search_time< StdClass >(get_range_t::random_unique(), "(rnd)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Extensions benchmark:" << BoostContName << std::endl;
extensions_time< BoostClass >(get_range_t::sorted_unique());
}
}
#endif //#ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP

View File

@@ -0,0 +1,34 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//Enable checks in debug mode
#ifndef NDEBUG
#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#endif
#include "bench_set.hpp"
#include <boost/container/set.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set<..., adaptive_pool> vs. set
launch_tests< set<int, std::less<int>, private_adaptive_pool<int> >, set<int> >
("set<int, ..., private_adaptive_pool<int>", "set<int>");
launch_tests< set<string, std::less<string>, private_adaptive_pool<string> >, set<string> >
("set<string, ..., private_adaptive_pool<string>", "set<string>");
return 0;
}

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "bench_set.hpp"
#include <boost/container/set.hpp>
#include <boost/container/allocator.hpp>
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set<..., version_2> vs. set
launch_tests< set<int, std::less<int>, allocator<int> >, set<int> >
("set<int, ..., allocator<int>", "set<int>");
launch_tests< set<string, std::less<string>, allocator<string> >, set<string> >
("set<string, ..., allocator<string>", "set<string>");
return 0;
}

View File

@@ -0,0 +1,38 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include <set>
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(AVL) vs set(RB)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type >, set<int> >
("set<int>(AVL)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree> >::type >, set<string> >
("set<string>(AVL)", "set<string>(RB)");
//set(AVL,sizeopt) vs set(AVL,!sizeopt)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type >
, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree>, optimize_size<false> >::type > >
("set<int>(AVL,sizeopt=true)", "set<int>(AVL,sizeopt=false)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree> >::type >
, set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree>, optimize_size<false> >::type > >
("set<string>(AVL,sizeopt=true)", "set<string>(AVL,sizeopt=false)");
return 0;
}

View File

@@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include <set>
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//multiset vs std::multiset
launch_tests< multiset<int> , std::multiset<int> >
("multiset<int>", "std::multiset<int>");
launch_tests< multiset<string> , std::multiset<string> >
("multiset<string>", "std::multiset<string>");
return 0;
}

View File

@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(RB) vs set(SG)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<scapegoat_tree> >::type >, set<int> >
("set<int>(SG)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<scapegoat_tree> >::type >, set<string> >
("set<string>(SG)", "set<string>(RB)");
return 0;
}

View File

@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(RB) vs set(SP)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<splay_tree> >::type >, set<int> >
("set<int>(SP)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<splay_tree> >::type >, set<string> >
("set<string>(SP)", "set<string>(RB)");
return 0;
}

View File

@@ -0,0 +1,144 @@
// benchmark based on: http://cpp-next.com/archive/2010/10/howards-stl-move-semantics-benchmark/
//
// @file bench_static_vector.cpp
// @date Aug 14, 2011
// @author Andrew Hundt <ATHundt@gmail.com>
//
// (C) Copyright 2011-2013 Andrew Hundt <ATHundt@gmail.com>
// (C) Copyright 2013-2013 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// @brief varray_benchmark.cpp compares the performance of boost::container::varray to boost::container::vector
#include "varray.hpp"
#include <boost/container/vector.hpp>
#include <boost/container/static_vector.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include "../test/movable_int.hpp"
#include <vector>
#include <iostream>
#include <boost/move/detail/nsec_clock.hpp>
#include <algorithm>
#include <exception>
#include <iomanip>
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
static const std::size_t N = 500;
#ifdef NDEBUG
static const std::size_t Iter = 50;
#else
static const std::size_t Iter = 5;
#endif
//#define BENCH_SIMPLE_CONSTRUCTION
//#define BENCH_TRIVIAL_TYPE
#ifdef BENCH_TRIVIAL_TYPE
typedef std::size_t basic_type_t;
#else
typedef boost::container::test::copyable_int basic_type_t;
#endif
template<typename T>
T &get_set(std::size_t)
{
#ifdef BENCH_SIMPLE_CONSTRUCTION
T &t = *new T(N);
for (std::size_t i = 0; i < N; ++i)
t[i] = basic_type_t(std::rand());
#else
T &t = *new T;
t.reserve(N);
for (std::size_t i = 0; i < N; ++i)
t.push_back(basic_type_t(std::rand()));
#endif
return t;
}
template<typename T>
T &generate()
{
T &v = *new T;
v.reserve(N);
for (std::size_t i = 0; i < N; ++i){
typename T::reference r = get_set<typename T::value_type>(i);
v.push_back(boost::move(r));
delete &r;
}
return v;
}
template<typename T>
cpu_times time_it()
{
cpu_timer sortTime,rotateTime,destructionTime;
sortTime.stop();rotateTime.stop();destructionTime.stop();
cpu_timer totalTime, constructTime;
std::srand (0);
for(std::size_t i = 0; i< Iter; ++i){
constructTime.resume();
{
T &v = generate<T>();
constructTime.stop();
sortTime.resume();
std::sort(v.begin(), v.end());
sortTime.stop();
rotateTime.resume();
std::rotate(v.begin(), v.begin() + std::ptrdiff_t(v.size()/2), v.end());
rotateTime.stop();
destructionTime.resume();
delete &v;
}
destructionTime.stop();
}
totalTime.stop();
std::cout << std::fixed << std::setw( 11 );
std::cout << " construction took " << double(constructTime.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " sort took " << double(sortTime.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " rotate took " << double(rotateTime.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " destruction took " << double(destructionTime.elapsed().wall)/double(1000000000) << "s\n";
std::cout << " Total time = " << double(totalTime.elapsed().wall)/double(1000000000) << "s\n";
return totalTime.elapsed();
}
void compare_times(cpu_times time_numerator, cpu_times time_denominator){
std::cout
<< "\n wall = " << ((double)time_numerator.wall/(double)time_denominator.wall) << "\n\n";
}
int main()
{
std::cout << "N = " << N << " Iter = " << Iter << "\n\n";
std::cout << "varray benchmark:" << std::endl;
cpu_times time_varray = time_it<boost::container::varray<boost::container::varray<basic_type_t,N>,N > >();
std::cout << "boost::container::static_vector benchmark" << std::endl;
cpu_times time_boost_static_vector = time_it<boost::container::static_vector<boost::container::static_vector<basic_type_t,N>,N > >();
std::cout << "boost::container::vector benchmark" << std::endl;
cpu_times time_boost_vector = time_it<boost::container::vector<boost::container::vector<basic_type_t> > >();
std::cout << "std::vector benchmark" << std::endl;
cpu_times time_standard_vector = time_it<std::vector<std::vector<basic_type_t> > >();
std::cout << "varray/boost::container::vector total time comparison:";
compare_times(time_varray, time_boost_vector);
std::cout << "varray/boost::container::static_vector total time comparison:";
compare_times(time_varray, time_boost_static_vector);
std::cout << "varray/std::vector total time comparison:";
compare_times(time_varray,time_standard_vector);
return 0;
}

View File

@@ -0,0 +1,298 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <vector>
#include <deque>
#include <boost/container/vector.hpp>
#include <boost/container/devector.hpp>
#include <boost/container/deque.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container/stable_vector.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <cstring> //std::strcmp
#include <boost/move/detail/nsec_clock.hpp>
#include <typeinfo>
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#endif
//capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace test {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//#pragma GCC diagnostic ignored "-Wunused-result"
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#pragma GCC diagnostic pop
#endif
using boost::move_detail::cpu_timer;
using boost::move_detail::cpu_times;
using boost::move_detail::nanosecond_type;
namespace bc = boost::container;
class MyInt
{
int int_;
public:
BOOST_CONTAINER_FORCEINLINE explicit MyInt(int i = 0)
: int_(i)
{}
BOOST_CONTAINER_FORCEINLINE MyInt(const MyInt &other)
: int_(other.int_)
{}
BOOST_CONTAINER_FORCEINLINE MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
BOOST_CONTAINER_FORCEINLINE ~MyInt()
{
int_ = 0;
}
};
template<class C, bool = boost::container::test::
has_member_function_callable_with_capacity<C>::value>
struct capacity_wrapper
{
BOOST_CONTAINER_FORCEINLINE static typename C::size_type get_capacity(const C &c)
{ return c.capacity(); }
BOOST_CONTAINER_FORCEINLINE static void set_reserve(C &c, typename C::size_type cp)
{ c.reserve(cp); }
};
template<class C>
struct capacity_wrapper<C, false>
{
BOOST_CONTAINER_FORCEINLINE static typename C::size_type get_capacity(const C &)
{ return 0u; }
BOOST_CONTAINER_FORCEINLINE static void set_reserve(C &, typename C::size_type )
{ }
};
const std::size_t RangeSize = 5;
struct insert_end_range
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return RangeSize; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int)
{ c.insert(c.end(), &a[0], &a[0]+RangeSize); }
const char *name() const
{ return "insert_end_range"; }
MyInt a[RangeSize];
};
struct insert_end_repeated
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return RangeSize; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int i)
{ c.insert(c.end(), RangeSize, MyInt(i)); }
BOOST_CONTAINER_FORCEINLINE const char *name() const
{ return "insert_end_repeated"; }
MyInt a[RangeSize];
};
struct push_back
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return 1; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int i)
{ c.push_back(MyInt(i)); }
BOOST_CONTAINER_FORCEINLINE const char *name() const
{ return "push_back"; }
};
struct insert_near_end_repeated
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return RangeSize; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int i)
{ c.insert(c.size() >= 2*RangeSize ? c.end()-2*RangeSize : c.begin(), RangeSize, MyInt(i)); }
BOOST_CONTAINER_FORCEINLINE const char *name() const
{ return "insert_near_end_repeated"; }
};
struct insert_near_end_range
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return RangeSize; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int)
{
c.insert(c.size() >= 2*RangeSize ? c.end()-2*RangeSize : c.begin(), &a[0], &a[0]+RangeSize);
}
BOOST_CONTAINER_FORCEINLINE const char *name() const
{ return "insert_near_end_range"; }
MyInt a[RangeSize];
};
struct insert_near_end
{
BOOST_CONTAINER_FORCEINLINE std::size_t capacity_multiplier() const
{ return 1; }
template<class C>
BOOST_CONTAINER_FORCEINLINE void operator()(C &c, int i)
{
typedef typename C::iterator it_t;
it_t it (c.end());
it -= static_cast<typename C::difference_type>(c.size() >= 2)*2;
c.insert(it, MyInt(i));
}
BOOST_CONTAINER_FORCEINLINE const char *name() const
{ return "insert_near_end"; }
};
template<class Container, class Operation>
void vector_test_template(std::size_t num_iterations, std::size_t num_elements, const char *cont_name)
{
typedef capacity_wrapper<Container> cpw_t;
Container c;
cpw_t::set_reserve(c, num_elements);
Operation op;
const typename Container::size_type multiplier = op.capacity_multiplier();
//Warm-up operation
for(std::size_t e = 0, max = num_elements/multiplier; e != max; ++e){
op(c, static_cast<int>(e));
}
c.clear();
cpu_timer timer;
const std::size_t max = num_elements/multiplier;
for(std::size_t r = 0; r != num_iterations; ++r){
//Unrolll the loop to avoid noise from loop code
int i = 0;
timer.resume();
for(std::size_t e = 0; e < max/16; ++e){
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
op(c, static_cast<int>(i++));
}
timer.stop();
c.clear();
}
timer.stop();
std::size_t capacity = cpw_t::get_capacity(c);
nanosecond_type nseconds = timer.elapsed().wall;
std::cout << cont_name << "->" << op.name() <<" ns: "
<< float(nseconds)/float(num_iterations*num_elements)
<< '\t'
<< "Capacity: " << capacity
<< "\n";
}
template<class Operation>
void test_vectors()
{
//#define SINGLE_TEST
#define SIMPLE_IT
#ifdef SINGLE_TEST
#ifdef NDEBUG
std::size_t numit [] = { 100 };
#else
std::size_t numit [] = { 20 };
#endif
std::size_t numele [] = { 10000 };
#elif defined SIMPLE_IT
std::size_t numit [] = { 100 };
std::size_t numele [] = { 10000 };
#else
#ifdef NDEBUG
unsigned int numit [] = { 1000, 10000, 100000, 1000000 };
#else
unsigned int numit [] = { 100, 1000, 10000, 100000 };
#endif
unsigned int numele [] = { 10000, 1000, 100, 10 };
#endif
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template< std::vector<MyInt, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "std::vector ");
vector_test_template< bc::vector<MyInt, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "vector ");
vector_test_template< bc::devector<MyInt, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "devector ");
vector_test_template< bc::small_vector<MyInt, 0, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "small_vector ");
vector_test_template< std::deque<MyInt, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "std::deque ");
vector_test_template< bc::deque<MyInt, std::allocator<MyInt> >, Operation >(numit[i], numele[i] , "deque ");
}
std::cout << "---------------------------------\n---------------------------------\n";
}
int main()
{
//end
test_vectors<push_back>();
test_vectors<insert_end_range>();
test_vectors<insert_end_repeated>();
//near end
test_vectors<insert_near_end>();
test_vectors<insert_near_end_range>();
test_vectors<insert_near_end_repeated>();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
// Boost.Container varray
//
// Copyright (c) 2012-2013 Andrew Hundt.
// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONTAINER_VARRAY_CONCEPT_HPP
#define BOOST_CONTAINER_VARRAY_CONCEPT_HPP
#include <boost/concept_check.hpp>
namespace boost { namespace container { namespace dtl { namespace concept {
/**
* VArrayStrategyConcept
*
* \brief Checks strategy for varray<Value,Capacity,Strategy>, which has similarities to std::allocator
* \ingroup varray
*/
template<typename Strategy>
struct VArrayStrategy {
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// typedefs are the same as in std::allocator
typedef typename Strategy::value_type value_type;
typedef typename Strategy::size_type size_type;
typedef typename Strategy::difference_type difference_type;
typedef typename Strategy::pointer pointer;
typedef typename Strategy::const_pointer const_pointer;
typedef typename Strategy::reference reference;
typedef typename Strategy::const_reference const_reference;
struct check_methods
{
static void apply()
{
Strategy const* str = 0;
// must implement allocate_failed
str->allocate_failed();
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(VArrayStrategy)
{
check_methods::apply();
}
#endif
};
}}}} // namespace boost::container::dtl::concept
#endif //BOOST_CONTAINER_VARRAY_CONCEPT_HPP

View File

@@ -0,0 +1,646 @@
// Boost.Container
//
// varray details
//
// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2013 Andrew Hundt.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
#define BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
#include <cstddef>
#include <cstring>
#include <memory>
#include <limits>
#include <boost/config.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/container/detail/addressof.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
#endif
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/move/algorithm.hpp>
#include <boost/move/traits.hpp>
#include <boost/move/utility_core.hpp>
// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
#if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
#include <vector>
#include <boost/container/vector.hpp>
#endif // BOOST_CONTAINER_VARRAY_ENABLE_ITERATORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
namespace boost { namespace container { namespace varray_detail {
namespace bcd = ::boost::container::dtl;
template <typename I>
struct are_elements_contiguous : boost::container::dtl::is_pointer<I>
{};
#if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
template <typename Pointer>
struct are_elements_contiguous<
bcd::vector_const_iterator<Pointer>
> : bcd::true_type
{};
template <typename Pointer>
struct are_elements_contiguous<
bcd::vector_iterator<Pointer>
> : bcd::true_type
{};
#if defined(BOOST_DINKUMWARE_STDLIB)
template <typename T>
struct are_elements_contiguous<
std::_Vector_const_iterator<T>
> : bcd::true_type
{};
template <typename T>
struct are_elements_contiguous<
std::_Vector_iterator<T>
> : bcd::true_type
{};
#elif defined(BOOST_GNU_STDLIB)
template <typename P, typename T, typename Allocator>
struct are_elements_contiguous<
__gnu_cxx::__normal_iterator<P, std::vector<T, Allocator> >
> : bcd::true_type
{};
#elif defined(_LIBCPP_VERSION)
// TODO - test it first
//template <typename P>
//struct are_elements_contiguous<
// __wrap_iter<P>
//> : bcd::true_type
//{};
#else // OTHER_STDLIB
// TODO - add other iterators implementations
#endif // STDLIB
#endif // BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
template <typename I, typename O>
struct are_corresponding :
bcd::bool_<
bcd::is_same<
bcd::remove_const<
typename ::boost::container::iterator_traits<I>::value_type
>,
bcd::remove_const<
typename ::boost::container::iterator_traits<O>::value_type
>
>::value &&
are_elements_contiguous<I>::value &&
are_elements_contiguous<O>::value
>
{};
template <typename I, typename V>
struct is_corresponding_value :
bcd::bool_<
bcd::is_same<
bcd::remove_const<typename ::boost::container::iterator_traits<I>::value_type>,
bcd::remove_const<V>
>::value
>
{};
// destroy(I, I)
template <typename I>
void destroy_dispatch(I /*first*/, I /*last*/, bcd::true_type const& /*is_trivially_destructible*/)
{}
template <typename I>
void destroy_dispatch(I first, I last, bcd::false_type const& /*is_trivially_destructible*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
for ( ; first != last ; ++first )
first->~value_type();
}
template <typename I>
void destroy(I first, I last)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
destroy_dispatch(first, last, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
}
// destroy(I)
template <typename I>
void destroy_dispatch(I /*pos*/,
bcd::true_type const& /*is_trivially_destructible*/)
{}
template <typename I>
void destroy_dispatch(I pos,
bcd::false_type const& /*is_trivially_destructible*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
pos->~value_type();
}
template <typename I>
void destroy(I pos)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
destroy_dispatch(pos, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
}
// copy(I, I, O)
template <typename I, typename O>
inline O copy_dispatch(I first, I last, O dst, bcd::true_type const& /*use_memmove*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
const std::size_t d = boost::container::iterator_udistance(first, last);
::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
return dst + d;
}
template <typename I, typename O>
inline O copy_dispatch(I first, I last, O dst, bcd::false_type const& /*use_memmove*/)
{
return std::copy(first, last, dst); // may throw
}
template <typename I, typename O>
inline O copy(I first, I last, O dst)
{
typedef bcd::bool_
< are_corresponding<I, O>::value &&
bcd::is_trivially_copy_assignable<typename ::boost::container::iterator_traits<O>::value_type>::value
> use_memmove;
return copy_dispatch(first, last, dst, use_memmove()); // may throw
}
// uninitialized_copy(I, I, O)
template <typename I, typename O>
inline
O uninitialized_copy_dispatch(I first, I last, O dst,
bcd::true_type const& /*use_memcpy*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
const std::size_t d = boost::container::iterator_udistance(first, last);
::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
return dst + d;
}
template <typename I, typename F>
inline
F uninitialized_copy_dispatch(I first, I last, F dst,
bcd::false_type const& /*use_memcpy*/)
{
return std::uninitialized_copy(first, last, dst); // may throw
}
template <typename I, typename F>
inline
F uninitialized_copy(I first, I last, F dst)
{
typedef bcd::bool_
< are_corresponding<I, F>::value &&
bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<F>::value_type>::value
> use_memcpy;
return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
}
// uninitialized_move(I, I, O)
template <typename I, typename O>
inline
O uninitialized_move_dispatch(I first, I last, O dst,
bcd::true_type const& /*use_memcpy*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
const std::size_t d = boost::container::iterator_udistance(first, last);
::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
return dst + d;
}
template <typename I, typename O>
inline
O uninitialized_move_dispatch(I first, I last, O dst,
bcd::false_type const& /*use_memcpy*/)
{
//return boost::uninitialized_move(first, last, dst); // may throw
O o = dst;
BOOST_TRY
{
typedef typename boost::container::iterator_traits<O>::value_type value_type;
for (; first != last; ++first, ++o )
new (boost::container::dtl::addressof(*o)) value_type(boost::move(*first));
}
BOOST_CATCH(...)
{
destroy(dst, o);
BOOST_RETHROW;
}
BOOST_CATCH_END
return dst;
}
template <typename I, typename O>
inline
O uninitialized_move(I first, I last, O dst)
{
typedef bcd::bool_
< are_corresponding<I, O>::value &&
bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
> use_memcpy;
return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
}
// TODO - move uses memmove - implement 2nd version using memcpy?
// move(I, I, O)
template <typename I, typename O>
inline
O move_dispatch(I first, I last, O dst,
bcd::true_type const& /*use_memmove*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
const std::size_t d = boost::container::iterator_udistance(first, last);
::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type)*d );
return dst + d;
}
template <typename I, typename O>
inline
O move_dispatch(I first, I last, O dst,
bcd::false_type const& /*use_memmove*/)
{
return boost::move(first, last, dst); // may throw
}
template <typename I, typename O>
inline
O move(I first, I last, O dst)
{
typedef bcd::bool_
< are_corresponding<I, O>::value &&
bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
> use_memmove;
return move_dispatch(first, last, dst, use_memmove()); // may throw
}
// move_backward(BDI, BDI, BDO)
template <typename BDI, typename BDO>
inline
BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
bcd::true_type const& /*use_memmove*/)
{
typedef typename ::boost::container::iterator_traits<BDI>::value_type value_type;
const std::size_t d = boost::container::iterator_udistance(first, last);
BDO foo(dst - d);
::memmove(boost::container::dtl::addressof(*foo), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
return foo;
}
template <typename BDI, typename BDO>
inline
BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
bcd::false_type const& /*use_memmove*/)
{
return boost::move_backward(first, last, dst); // may throw
}
template <typename BDI, typename BDO>
inline
BDO move_backward(BDI first, BDI last, BDO dst)
{
typedef bcd::bool_
< are_corresponding<BDI, BDO>::value &&
bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<BDO>::value_type>::value
> use_memmove;
return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
}
template <typename T>
struct has_nothrow_move : public
bcd::bool_<
::boost::has_nothrow_move<
typename bcd::remove_const<T>::type
>::value
||
::boost::has_nothrow_move<T>::value
>
{};
// uninitialized_move_if_noexcept(I, I, O)
template <typename I, typename O>
inline
O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
{ return uninitialized_move(first, last, dst); }
template <typename I, typename O>
inline
O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
{ return uninitialized_copy(first, last, dst); }
template <typename I, typename O>
inline
O uninitialized_move_if_noexcept(I first, I last, O dst)
{
typedef has_nothrow_move<
typename ::boost::container::iterator_traits<O>::value_type
> use_move;
return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
}
// move_if_noexcept(I, I, O)
template <typename I, typename O>
inline
O move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
{ return move(first, last, dst); }
template <typename I, typename O>
inline
O move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
{ return copy(first, last, dst); }
template <typename I, typename O>
inline
O move_if_noexcept(I first, I last, O dst)
{
typedef has_nothrow_move<
typename ::boost::container::iterator_traits<O>::value_type
> use_move;
return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
}
// uninitialized_fill(I, I)
template <typename I>
inline
void uninitialized_fill_dispatch(I , I ,
bcd::true_type const& /*is_trivially_default_constructible*/,
bcd::true_type const& /*disable_trivial_init*/)
{}
template <typename I>
inline
void uninitialized_fill_dispatch(I first, I last,
bcd::true_type const& /*is_trivially_default_constructible*/,
bcd::false_type const& /*disable_trivial_init*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
for ( ; first != last ; ++first )
new (boost::container::dtl::addressof(*first)) value_type();
}
template <typename I, typename DisableTrivialInit>
inline
void uninitialized_fill_dispatch(I first, I last,
bcd::false_type const& /*is_trivially_default_constructible*/,
DisableTrivialInit const& /*not_used*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
I it = first;
BOOST_TRY
{
for ( ; it != last ; ++it )
new (boost::container::dtl::addressof(*it)) value_type(); // may throw
}
BOOST_CATCH(...)
{
destroy(first, it);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
template <typename I, typename DisableTrivialInit>
inline
void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
uninitialized_fill_dispatch(first, last
, bcd::bool_<bcd::is_trivially_default_constructible<value_type>::value>()
, disable_trivial_init); // may throw
}
// construct(I)
template <typename I>
inline
void construct_dispatch(bcd::true_type const& /*dont_init*/, I /*pos*/)
{}
template <typename I>
inline
void construct_dispatch(bcd::false_type const& /*dont_init*/, I pos)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
new (static_cast<void*>(::boost::container::dtl::addressof(*pos))) value_type(); // may throw
}
template <typename DisableTrivialInit, typename I>
inline
void construct(DisableTrivialInit const&, I pos)
{
typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
bcd::bool_<
bcd::is_trivially_default_constructible<value_type>::value &&
DisableTrivialInit::value
> dont_init;
construct_dispatch(dont_init(), pos); // may throw
}
// construct(I, V)
template <typename I, typename V>
inline
void construct_dispatch(I pos, V const& v, bcd::true_type const& /*use_memcpy*/)
{
::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
}
template <typename I, typename P>
inline
void construct_dispatch(I pos, P const& p,
bcd::false_type const& /*use_memcpy*/)
{
typedef typename ::boost::container::iterator_traits<I>::value_type V;
new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(p); // may throw
}
template <typename DisableTrivialInit, typename I, typename P>
inline
void construct(DisableTrivialInit const&, I pos, P const& p)
{
typedef bcd::bool_
< is_corresponding_value<I, P>::value &&
bcd::is_trivially_copy_constructible<P>::value
> use_memcpy;
construct_dispatch(pos, p, use_memcpy()); // may throw
}
// Needed by push_back(V &&)
template <typename DisableTrivialInit, typename I, typename P>
inline
void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
{
typedef typename ::boost::container::iterator_traits<I>::value_type V;
new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::move(p)); // may throw
}
// Needed by emplace_back() and emplace()
#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename DisableTrivialInit, typename I, class ...Args>
inline
void construct(DisableTrivialInit const&,
I pos,
BOOST_FWD_REF(Args) ...args)
{
typedef typename ::boost::container::iterator_traits<I>::value_type V;
new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
}
#else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
// BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0
// !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
// which means that version with one parameter may take V const& v
#define BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE(N) \
template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline void construct(DisableTrivialInit const&, I pos, BOOST_FWD_REF(P) p BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
{\
typedef typename ::boost::container::iterator_traits<I>::value_type V;\
new (static_cast<void*>(boost::container::dtl::addressof(*pos)))\
V(::boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/\
}
BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE)
#undef BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE
#endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
// assign(I, V)
template <typename I, typename V>
inline
void assign_dispatch(I pos, V const& v,
bcd::true_type const& /*use_memcpy*/)
{
::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
}
template <typename I, typename V>
inline
void assign_dispatch(I pos, V const& v,
bcd::false_type const& /*use_memcpy*/)
{
*pos = v; // may throw
}
template <typename I, typename V>
inline
void assign(I pos, V const& v)
{
typedef bcd::bool_
< is_corresponding_value<I, V>::value &&
bcd::is_trivially_copy_assignable<V>::value
> use_memcpy;
assign_dispatch(pos, v, use_memcpy()); // may throw
}
template <typename I, typename V>
inline
void assign(I pos, BOOST_RV_REF(V) v)
{
*pos = boost::move(v); // may throw
}
// uninitialized_copy_s
template <typename I, typename F>
inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
{
std::size_t count = 0;
F it = dest;
BOOST_TRY
{
for ( ; first != last ; ++it, ++first, ++count )
{
if ( max_count <= count )
return (std::numeric_limits<std::size_t>::max)();
// dummy 0 as DisableTrivialInit
construct(0, it, *first); // may throw
}
}
BOOST_CATCH(...)
{
destroy(dest, it);
BOOST_RETHROW;
}
BOOST_CATCH_END
return count;
}
// scoped_destructor
template<class T>
class scoped_destructor
{
public:
scoped_destructor(T * ptr) : m_ptr(ptr) {}
~scoped_destructor()
{
if(m_ptr)
destroy(m_ptr);
}
void release() { m_ptr = 0; }
private:
T * m_ptr;
};
}}} // namespace boost::container::varray_detail
#endif // BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP

File diff suppressed because it is too large Load Diff