Created
December 2, 2014 03:16
-
-
Save randomphrase/aad0615a5ac6696e08f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- mode: c++; c-basic-offset: 4 -*- | |
#include <boost/timer.hpp> | |
#include <algorithm> | |
#include <random> | |
#include <cstring> | |
#include <iostream> | |
#include <iomanip> | |
#include <stdexcept> | |
const unsigned WARMUP = 5; | |
const unsigned ITERATIONS = 10'000'000; | |
template <std::size_t Size, typename CopyFn> | |
double TimeArrayCopy(CopyFn copyFn = CopyFn()) | |
{ | |
using namespace std; | |
char src[Size]; | |
char dst[Size]; | |
// generate random chars for the source array - use constant seed | |
mt19937 gen(1); | |
uniform_int_distribution<char> dis('a', 'z'); | |
generate(begin(src), end(src), [&](){ return dis(gen); }); | |
// generate a checksum for the source array (mainly to defeat the optimizer) | |
static volatile std::size_t src_checksum = accumulate( | |
begin(src), end(src), 0u, [] (unsigned s, char ch) { return (s + ch) % 256; }); | |
for (unsigned i = 0; i < WARMUP; ++i) { | |
copyFn(begin(src), end(src), begin(dst)); | |
} | |
boost::timer time; | |
for (unsigned i = 0; i < ITERATIONS; ++i) { | |
copyFn(begin(src), end(src), begin(dst)); | |
} | |
auto elapsed = time.elapsed(); | |
static volatile std::size_t dst_checksum = accumulate( | |
begin(dst), end(dst), 0u, [] (unsigned s, char ch) { return (s + ch) % 256; }); | |
if (src_checksum != dst_checksum) { | |
throw std::runtime_error("checksum mismatch"); | |
} | |
return elapsed; | |
} | |
void Report(const char * name, double baseline, double result) | |
{ | |
std::cout << std::setw(15) << name << ": " | |
<< std::fixed << result | |
<< " (" << std::fixed << result / baseline << " times baseline)" << std::endl; | |
} | |
template <std::size_t Size> | |
void ArrayCopy() | |
{ | |
auto baseline = TimeArrayCopy<Size>( | |
[] (const char *begin, const char *end, char *dest) { | |
while (begin != end) { | |
*dest++ = *begin++; | |
} | |
}); | |
std::cout << "Array copy (size = " << Size << "), baseline : " << baseline << std::endl; | |
Report("std::memcpy", baseline, TimeArrayCopy<Size>( | |
[] (const char *begin, const char *end, char *dest) { | |
std::memcpy(dest, begin, end - begin); | |
})); | |
Report("std::memmove", baseline, TimeArrayCopy<Size>( | |
[] (const char *begin, const char *end, char *dest) { | |
std::memmove(dest, begin, end - begin); | |
})); | |
Report("std::copy", baseline, TimeArrayCopy<Size>( | |
[] (const char *begin, const char *end, char *dest) { | |
std::copy(begin, end, dest); | |
})); | |
} | |
int main() | |
{ | |
std::cout << std::setprecision(8); | |
try { | |
ArrayCopy<16>(); | |
ArrayCopy<128>(); | |
ArrayCopy<1024>(); | |
} catch(std::exception& e) { | |
std::cerr << e.what() << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment