2
0
mirror of https://github.com/boostorg/pool.git synced 2026-01-26 06:42:25 +00:00
Files
pool/example/time_pool_alloc.cpp
John Maddock c7b0d00943 Add some debugging code.
Add tentative Valgrind support.
Change singleton usage to address issue 5526 by making singletons eternal.
Add Valgrind tests.
Update docs to match.
Refs #5526.

[SVN r73121]
2011-07-15 17:40:49 +00:00

559 lines
17 KiB
C++

// Copyright (C) 2000, 2001 Stephen Cleary
//
// 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)
#include <boost/pool/pool_alloc.hpp>
#include <boost/pool/object_pool.hpp>
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <ctime>
#include <cerrno>
#include "sys_allocator.hpp"
unsigned long num_ints;
unsigned long num_loops = 10;
unsigned l;
template <unsigned N>
struct larger_structure
{
char data[N];
};
unsigned test_number;
template <unsigned N>
static void timing_test_alloc_larger()
{
typedef boost::fast_pool_allocator<larger_structure<N>,
boost::default_user_allocator_new_delete,
boost::details::pool::null_mutex> alloc;
typedef boost::fast_pool_allocator<larger_structure<N> > alloc_sync;
double end[1][6];
std::clock_t start;
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::allocator<larger_structure<N> > a;
for (unsigned long i = 0; i < num_ints; ++i)
a.deallocate(a.allocate(1), 1);
}
end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
std::free(std::malloc(sizeof(larger_structure<N>)));
}
end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
delete new (std::nothrow) larger_structure<N>;
}
end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
alloc::deallocate(alloc::allocate());
}
end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
alloc_sync::deallocate(alloc_sync::allocate());
}
end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
boost::pool<> p(sizeof(larger_structure<N>));
for (unsigned long i = 0; i < num_ints; ++i)
{
void * const t = p.malloc();
if (t != 0)
p.free(t);
}
}
end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
std::cout << "Test " << test_number++ << ": Alloc & Dealloc " << num_ints << " structures of size " << sizeof(larger_structure<N>) << ":" << std::endl;
std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
}
static void timing_test_alloc()
{
typedef boost::fast_pool_allocator<int,
boost::default_user_allocator_new_delete,
boost::details::pool::null_mutex> alloc;
typedef boost::fast_pool_allocator<int> alloc_sync;
double end[2][6];
std::clock_t start;
int ** p = new int*[num_ints];
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::allocator<int> a;
for (unsigned long i = 0; i < num_ints; ++i)
a.deallocate(a.allocate(1), 1);
}
end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
std::free(std::malloc(sizeof(int)));
}
end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
delete new (std::nothrow) int;
}
end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
alloc::deallocate(alloc::allocate());
}
end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
alloc_sync::deallocate(alloc_sync::allocate());
}
end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
boost::pool<> p(sizeof(int));
for (unsigned long i = 0; i < num_ints; ++i)
{
void * const t = p.malloc();
if (t != 0)
p.free(t);
}
}
end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::allocator<int> a;
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = a.allocate(1);
for (unsigned long i = 0; i < num_ints; ++i)
a.deallocate(p[i], 1);
}
end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = (int *) std::malloc(sizeof(int));
for (unsigned long i = 0; i < num_ints; ++i)
std::free(p[i]);
}
end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = new (std::nothrow) int;
for (unsigned long i = 0; i < num_ints; ++i)
delete p[i];
}
end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = alloc::allocate();
for (unsigned long i = 0; i < num_ints; ++i)
alloc::deallocate(p[i]);
}
end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = alloc_sync::allocate();
for (unsigned long i = 0; i < num_ints; ++i)
alloc_sync::deallocate(p[i]);
}
end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
boost::pool<> pl(sizeof(int));
for (unsigned long i = 0; i < num_ints; ++i)
p[i] = reinterpret_cast<int *>(pl.malloc());
for (unsigned long i = 0; i < num_ints; ++i)
if (p[i] != 0)
pl.free(p[i]);
}
end[1][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
delete [] p;
std::cout << "Test 3: Alloc & Dealloc " << num_ints << " ints:" << std::endl;
std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
std::cout << "Test 4: Alloc " << num_ints << " ints & Dealloc " << num_ints << " ints:" << std::endl;
std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
std::cout << " Pool: " << end[1][5] << " seconds" << std::endl;
}
static void timing_test_containers()
{
typedef boost::pool_allocator<int,
boost::default_user_allocator_new_delete,
boost::details::pool::null_mutex> alloc;
typedef boost::pool_allocator<int> alloc_sync;
typedef boost::fast_pool_allocator<int,
boost::default_user_allocator_new_delete,
boost::details::pool::null_mutex> fast_alloc;
typedef boost::fast_pool_allocator<int> fast_alloc_sync;
double end[3][5];
std::clock_t start;
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::vector<int, std::allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::vector<int, malloc_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::vector<int, new_delete_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::vector<int, alloc> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::vector<int, alloc_sync> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::set<int, std::less<int>, std::allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.insert(0);
}
end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::set<int, std::less<int>, malloc_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.insert(0);
}
end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::set<int, std::less<int>, new_delete_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.insert(0);
}
end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::set<int, std::less<int>, fast_alloc> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.insert(0);
}
end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::set<int, std::less<int>, fast_alloc_sync> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.insert(0);
}
end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::list<int, std::allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[2][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::list<int, malloc_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[2][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::list<int, new_delete_allocator<int> > x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[2][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::list<int, fast_alloc> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[2][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
start = std::clock();
for(l = 0; l < num_loops; ++l)
{
std::list<int, fast_alloc_sync> x;
for (unsigned long i = 0; i < num_ints; ++i)
x.push_back(0);
}
end[2][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
std::cout << "Test 0: Insertion & deletion of " << num_ints << " ints in a vector:" << std::endl;
std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
std::cout << " Pool: not possible" << std::endl;
std::cout << "Test 1: Insertion & deletion of " << num_ints << " ints in a set:" << std::endl;
std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
std::cout << " Pool: not possible" << std::endl;
std::cout << "Test 2: Insertion & deletion of " << num_ints << " ints in a list:" << std::endl;
std::cout << " std::allocator: " << end[2][0] << " seconds" << std::endl;
std::cout << " malloc/free: " << end[2][1] << " seconds" << std::endl;
std::cout << " new/delete: " << end[2][2] << " seconds" << std::endl;
std::cout << " Pool Alloc: " << end[2][3] << " seconds" << std::endl;
std::cout << " Pool /w Sync: " << end[2][4] << " seconds" << std::endl;
std::cout << " Pool: not possible" << std::endl;
}
int main(int argc, char * argv[])
{
if (argc != 1 && argc != 2)
{
std::cerr << "Usage: " << argv[0]
<< " [number_of_ints_to_use_each_try]" << std::endl;
return 1;
}
errno = 0;
if (argc == 2)
{
num_ints = std::strtoul(argv[1], 0, 10);
if (errno != 0)
{
std::cerr << "Cannot convert number \"" << argv[1] << '"' << std::endl;
return 2;
}
}
else
num_ints = 700000;
#ifndef _NDEBUG
num_ints /= 100;
#endif
try
{
timing_test_containers();
timing_test_alloc();
test_number = 5;
timing_test_alloc_larger<64>();
test_number = 6;
timing_test_alloc_larger<256>();
test_number = 7;
timing_test_alloc_larger<4096>();
}
catch (const std::bad_alloc &)
{
std::cerr << "Timing tests ran out of memory; try again with a lower value for number of ints"
<< " (current value is " << num_ints << ")" << std::endl;
return 3;
}
catch (const std::exception & e)
{
std::cerr << "Error: " << e.what() << std::endl;
return 4;
}
catch (...)
{
std::cerr << "Unknown error" << std::endl;
return 5;
}
return 0;
}
/*
Output:
MSVC 10.0 using mutli-threaded DLL
time_pool_alloc.cpp
Creating library J:\Cpp\pool\pool\Release\alloc_example.lib and object J:\Cpp\pool\pool\Release\alloc_example.exp
Generating code
Finished generating code
alloc_example.vcxproj -> J:\Cpp\pool\pool\Release\alloc_example.exe
Test 0: Insertion & deletion of 700000 ints in a vector:
std::allocator: 0.062 seconds
malloc/free: 0.078 seconds
new/delete: 0.078 seconds
Pool Alloc: 0.328 seconds
Pool /w Sync: 0.343 seconds
Pool: not possible
Test 1: Insertion & deletion of 700000 ints in a set:
std::allocator: 0.561 seconds
malloc/free: 0.546 seconds
new/delete: 0.562 seconds
Pool Alloc: 0.109 seconds
Pool /w Sync: 0.094 seconds
Pool: not possible
Test 2: Insertion & deletion of 700000 ints in a list:
std::allocator: 0.671 seconds
malloc/free: 0.67 seconds
new/delete: 0.671 seconds
Pool Alloc: 0.094 seconds
Pool /w Sync: 0.093 seconds
Pool: not possible
Test 3: Alloc & Dealloc 700000 ints:
std::allocator: 0.5 seconds
malloc/free: 0.468 seconds
new/delete: 0.592 seconds
Pool Alloc: 0.032 seconds
Pool /w Sync: 0.015 seconds
Pool: 0.016 seconds
Test 4: Alloc 700000 ints & Dealloc 700000 ints:
std::allocator: 0.593 seconds
malloc/free: 0.577 seconds
new/delete: 0.717 seconds
Pool Alloc: 0.032 seconds
Pool /w Sync: 0.031 seconds
Pool: 0.047 seconds
Test 5: Alloc & Dealloc 700000 structures of size 64:
std::allocator: 0.499 seconds
malloc/free: 0.483 seconds
new/delete: 0.624 seconds
Pool Alloc: 0.016 seconds
Pool /w Sync: 0.031 seconds
Pool: 0.016 seconds
Test 6: Alloc & Dealloc 700000 structures of size 256:
std::allocator: 0.499 seconds
malloc/free: 0.484 seconds
new/delete: 0.639 seconds
Pool Alloc: 0.016 seconds
Pool /w Sync: 0.015 seconds
Pool: 0.016 seconds
Test 7: Alloc & Dealloc 700000 structures of size 4096:
std::allocator: 0.515 seconds
malloc/free: 0.515 seconds
new/delete: 0.639 seconds
Pool Alloc: 0.031 seconds
Pool /w Sync: 0.016 seconds
Pool: 0.016 seconds
*/