blob: 08bc65791a46b75fa04445c33cf00fb180cc8290 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2010 Tim Blechmann
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)
=============================================================================*/
#include <algorithm>
#include <vector>
#include <boost/foreach.hpp>
#include "high_resolution_timer.hpp"
#include <boost/heap/heap_merge.hpp>
#if defined(__GNUC__) && (!defined __INTEL_COMPILER)
#define no_inline __attribute__ ((noinline))
#else
#define no_inline
#endif
typedef std::vector<int> test_data;
const int num_benchmarks = 1;
inline test_data make_sequential_test_data(int size)
{
test_data v(size);
for (int i = 0; i != size; ++i)
v[i] = i;
return v;
}
inline test_data make_test_data(int size)
{
test_data v = make_sequential_test_data(size);
std::random_shuffle(v.begin(), v.end());
return v;
}
const int max_data = 20;
test_data const & get_data(int index)
{
static std::vector <test_data> data;
if (data.empty())
for (int i = 0; i != num_benchmarks; ++i)
data.push_back(make_test_data((1<<(max_data+1))+1024));
return data[index];
}
#define DEFINE_BENCHMARKS_SELECTOR(SUFFIX) \
struct make_##SUFFIX \
{ \
template <typename heap> \
struct rebind { \
typedef run_##SUFFIX<heap> type; \
}; \
};
template <typename pri_queue>
void fill_heap(pri_queue & q, int index, int size, int offset = 0)
{
test_data const & data = get_data(index);
for (int i = 0; i != size + 1; ++i) {
q.push(data[i]);
int top = q.top();
q.pop();
q.push(top);
}
}
template <typename pri_queue,
typename handle_container
>
void fill_heap_with_handles(pri_queue & q, handle_container & handles, int index, int size, int offset = 0)
{
test_data const & data = get_data(index);
for (int i = 0; i != size + 1; ++i) {
handles[i] = q.push(data[i]);
if (i > 0) {
typename pri_queue::handle_type last = handles[i-1];
int val = *last;
q.erase(last);
handles[i-1] = q.push(val);
}
}
}
template <typename pri_queue>
struct run_sequential_push
{
run_sequential_push(int size):
size(size)
{}
void prepare(int index)
{
q.clear();
fill_heap(q, index, size);
}
no_inline void operator()(int index)
{
test_data const & data = get_data(index);
for (int i = 0; i != 16; ++i)
q.push(data[(1<<max_data) + i]);
}
pri_queue q;
int size;
};
DEFINE_BENCHMARKS_SELECTOR(sequential_push)
template <typename pri_queue>
struct run_sequential_pop
{
run_sequential_pop(int size):
size(size)
{}
void prepare(int index)
{
q.clear();
fill_heap(q, index, size);
}
no_inline void operator()(int index)
{
for (int i = 0; i != 16; ++i)
q.pop();
}
pri_queue q;
int size;
};
DEFINE_BENCHMARKS_SELECTOR(sequential_pop)
template <typename pri_queue>
struct run_sequential_increase
{
run_sequential_increase(int size):
size(size), handles(size)
{}
void prepare(int index)
{
q.clear();
fill_heap_with_handles(q, handles, index, size);
}
no_inline void operator()(int index)
{
test_data const & data = get_data(index);
for (int i = 0; i != 16; ++i)
q.increase(handles[i], data[i] + (1<<max_data));
}
pri_queue q;
int size;
std::vector<typename pri_queue::handle_type> handles;
};
DEFINE_BENCHMARKS_SELECTOR(sequential_increase)
template <typename pri_queue>
struct run_sequential_decrease
{
run_sequential_decrease(int size):
size(size), handles(size)
{}
void prepare(int index)
{
q.clear();
fill_heap_with_handles(q, handles, index, size);
}
no_inline void operator()(int index)
{
test_data const & data = get_data(index);
for (int i = 0; i != 16; ++i)
q.decrease(handles[i], data[i] + (1<<max_data));
}
pri_queue q;
int size;
std::vector<typename pri_queue::handle_type> handles;
};
DEFINE_BENCHMARKS_SELECTOR(sequential_decrease)
template <typename pri_queue>
struct run_merge_and_clear
{
run_merge_and_clear(int size):
size(size)
{}
void prepare(int index)
{
q.clear();
r.clear();
fill_heap(q, index, size);
fill_heap(r, index, size, size);
}
no_inline void operator()(int index)
{
boost::heap::heap_merge(q, r);
}
pri_queue q, r;
int size;
};
DEFINE_BENCHMARKS_SELECTOR(merge_and_clear)
template <typename pri_queue>
struct run_equivalence
{
run_equivalence(int size):
size(size)
{}
void prepare(int index)
{
q.clear();
r.clear();
s.clear();
fill_heap(q, index, size);
fill_heap(r, index, size, size);
fill_heap(s, index, size);
}
no_inline bool operator()(int index)
{
return (q == r) ^ (q == s);
}
pri_queue q, r, s;
int size;
};
DEFINE_BENCHMARKS_SELECTOR(equivalence)
template <typename benchmark>
inline double run_benchmark(benchmark & b)
{
boost::high_resolution_timer timer;
std::vector<double> results;
for (int i = 0; i != num_benchmarks; ++i)
{
b.prepare(i);
timer.restart();
b(i);
double t = timer.elapsed();
results.push_back(t);
}
return results.at(results.size()/2); // median
}