TestBenchmark
// Test::Benchmark example | |
// http://gist.github.com/malcom/5759223 | |
#include "testbenchm.hpp" | |
#include <iostream> | |
#include <iomanip> | |
#include <memory> | |
#include <random> | |
#include <algorithm> // std::generate_n | |
#include <functional> // std::hash | |
// Hash function based of implementation available at | |
// http://www.partow.net/programming/hashfunctions/ | |
uint32_t RSHash(const char* data, size_t len) { | |
uint32_t b = 378551; | |
uint32_t a = 63689; | |
uint32_t hash = 0; | |
for (size_t i = 0; i < len; i++) { | |
hash = hash * a + data[i]; | |
a = a * b; | |
} | |
return hash; | |
} | |
uint32_t JSHash(const char* data, size_t len) { | |
uint32_t hash = 1315423911; | |
for (size_t i = 0; i < len; i++) | |
hash ^= ((hash << 5) + data[i] + (hash >> 2)); | |
return hash; | |
} | |
uint32_t ELFHash(const char* data, size_t len) { | |
uint32_t hash = 0; | |
uint32_t x = 0; | |
for (size_t i = 0; i < len; i++) { | |
hash = (hash << 4) + data[i]; | |
x = hash & 0xF0000000L; | |
if (x != 0) | |
hash ^= (x >> 24); | |
hash &= ~x; | |
} | |
return hash; | |
} | |
uint32_t DJBHash(const char* data, size_t len) { | |
uint32_t hash = 5381; | |
for (size_t i = 0; i < len; i++) | |
hash = ((hash << 5) + hash) + data[i]; | |
return hash; | |
} | |
uint32_t STLHash(const char* data, size_t len) { | |
uint32_t hash = 0; | |
std::hash<char> hasher; | |
for (size_t i = 0; i < len; ++i) | |
hash = hash ^ hasher(data[i]); | |
return hash; | |
} | |
int main(int argc, char* argv[]) { | |
const int Length = 256 * 1024; | |
const int Count = 1000; | |
typedef std::chrono::microseconds Time; | |
std::unique_ptr<char[]> data(new char[Length]); | |
// randomize data | |
{ | |
static const char alphanum[] = | |
"0123456789" | |
"!@#$%^&*" | |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
"abcdefghijklmnopqrstuvwxyz"; | |
std::default_random_engine rng; | |
std::uniform_int_distribution<> dist(0, sizeof(alphanum) -1); | |
char* out = std::generate_n(data.get(), Length - 1, [&](){ return alphanum[dist(rng)]; }); | |
*out = '\0'; | |
} | |
//typedef uint32_t (*hash_func_t)(const char*, size_t); | |
typedef decltype(&STLHash) hash_func_t; | |
struct function_t { | |
hash_func_t func; | |
const char* name; | |
}; | |
const function_t functions[] = { | |
{ RSHash, "RS-Hash Function" }, | |
{ JSHash, "JS-Hash Function" }, | |
{ ELFHash, "ELF-Hash Function" }, | |
{ DJBHash, "DJB-Hash Function" }, | |
{ STLHash, "STL-Hash Function" }, | |
}; | |
namespace TB = Test::Benchmark; | |
std::cout << "Sample hash operations perfomance test\n\n"; | |
std::cout << "Count: " << Count << ", Buffer length: " << Length << "\n\n"; | |
std::cout << " name avg min max\n"; | |
for (auto& f : functions) { | |
TB::Result::Data<Time> result; | |
TB::Run<Time>( [&]() { f.func(data.get(), Length); }, Count, result); | |
std::cout | |
<< std::left | |
<< std::setw(20) << f.name << " " | |
<< std::right | |
<< std::setw(8) << TB::Result::Mean<typename Time::rep>(result) << " " | |
<< std::setw(8) << TB::Result::Min<typename Time::rep>(result) << " " | |
<< std::setw(8) << TB::Result::Max<typename Time::rep>(result) << " " | |
<< std::endl; | |
} | |
return 0; | |
} |
// TestBenchmark | |
// Marcin 'Malcom' Malich <me@malcom.pl> | |
// http://blog.malcom.pl/2013/06/11/prosty-benchmark-testow/ | |
// MIT License | |
#ifndef TEST_BENCHMARK_HPP | |
#define TEST_BENCHMARK_HPP | |
#include <vector> | |
#include <iterator> | |
#include <algorithm> | |
#include <numeric> | |
#include <chrono> | |
namespace Test { | |
namespace Benchmark { | |
namespace Result { | |
#ifdef _MSC_VER | |
// VS2k12 not support 'Alias templates' | |
template<typename Time> | |
struct Data : public std::vector<typename Time::rep> {}; | |
#else | |
template<typename Time> using Data = std::vector<typename Time::rep>; | |
#endif | |
template<typename T, typename D> | |
T Count(const D& data) { | |
return std::distance(std::begin(data), std::end(data)); | |
} | |
template<typename T, typename D> | |
T Min(const D& data) { | |
return *std::min_element(std::begin(data), std::end(data)); | |
} | |
template<typename T, typename D> | |
T Max(const D& data) { | |
return *std::max_element(std::begin(data), std::end(data)); | |
} | |
template<typename T, typename D> | |
T Mean(const D& data) { | |
auto n = std::distance(std::begin(data), std::end(data)); | |
return std::accumulate(std::begin(data), std::end(data), T()) / n; | |
} | |
} // namespace Result | |
template<typename Time, typename F> | |
void Run(F func, int count, Result::Data<Time>& data) { | |
for (int i = 0; i < count; i++) { | |
auto t1 = std::chrono::high_resolution_clock::now(); | |
func(); | |
auto t2 = std::chrono::high_resolution_clock::now(); | |
std::back_inserter(data) = std::chrono::duration_cast<Time>(t2 - t1).count(); | |
} | |
} | |
} // namespace Benchmark | |
} // namespace Test | |
#endif // TEST_BENCHMARK_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment