Skip to content

Instantly share code, notes, and snippets.

@malcom
Last active December 18, 2015 09:09
Show Gist options
  • Save malcom/5759223 to your computer and use it in GitHub Desktop.
Save malcom/5759223 to your computer and use it in GitHub Desktop.
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