#include <assert.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <vector>
#include <map>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <numeric>
#include <cmath>
#include <algorithm>
#include <limits>
const unsigned int buffermin = 16;
const unsigned int buffermax = 16 * 65536;
const unsigned int baserepeatsize = 65536;
const unsigned int minrepeats = 4;
const unsigned int measureruns = 16;
#ifndef _MSC_VER
#include <sys/time.h>
#else
#include <windows.h>
#endif
inline double timestamp()
{
#ifndef _MSC_VER
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec * 0.000001;
#else
return timeGetTime() / 1000.0;
#endif
}
unsigned char enckey[32];
unsigned char enciv[16];
unsigned char buffer[buffermax];
unsigned int bufferlen;
template <void (*testfunc)()>
void run_test(const char* logfile)
{
std::cout << "Speed testing for " << logfile << "\n";
std::map<unsigned int, std::vector<double> > timelog;
for(unsigned int fullrun = 0; fullrun < measureruns; ++fullrun)
{
unsigned int repeatsize = baserepeatsize;
for(unsigned int bufflen = buffermin; bufflen <= buffermax; bufflen *= 2)
{
REDO:
unsigned int repeat = repeatsize / bufflen;
if (repeat < minrepeats) repeat = minrepeats;
bufferlen = bufflen;
for(unsigned int i = 0; i < bufferlen; ++i)
buffer[i] = (uint8_t)i;
double ts1 = timestamp();
for(unsigned int testrun = 0; testrun < repeat; ++testrun)
{
testfunc();
}
double ts2 = timestamp();
double tsdelta = ts2 - ts1;
if (tsdelta < 0.5) {
printf("Run %d bufferlen %d repeat %d took only %.2f sec. Increasing repetitons.\n",
fullrun, bufferlen, repeat, tsdelta);
repeatsize *= 2;
goto REDO;
}
else {
printf("Run %d bufferlen %d repeat %d took %.2f sec.\n",
fullrun, bufferlen, repeat, tsdelta);
}
for(unsigned int i = 0; i < bufferlen; ++i)
assert(buffer[i] == (uint8_t)i);
timelog[bufferlen].push_back( tsdelta / (double)repeat );
}
}
std::ofstream of (logfile);
for(std::map<unsigned int, std::vector<double> >::const_iterator ti = timelog.begin();
ti != timelog.end(); ++ti)
{
const std::vector<double>& timelist = ti->second;
double average = std::accumulate(timelist.begin(), timelist.end(), 0.0) / timelist.size();
double variance = 0.0;
for(unsigned int i = 0; i < timelist.size(); ++i)
{
variance += (timelist[i] - average) * (timelist[i] - average);
}
variance = variance / (timelist.size() - 1);
double stddev = std::sqrt(variance);
if (timelist.size() == 1) {
variance = stddev = 0.0;
}
double vmin = *std::min_element(timelist.begin(), timelist.end());
double vmax = *std::max_element(timelist.begin(), timelist.end());
of << std::setprecision(16);
of << ti->first << " " << average << " " << stddev << " " << vmin << " " << vmax << "\n";
}
of << "\n\n";
for(std::map<unsigned int, std::vector<double> >::const_iterator ti = timelog.begin();
ti != timelog.end(); ++ti)
{
const std::vector<double>& timelist = ti->second;
double average = 0.0;
double vmin = std::numeric_limits<double>::infinity();
double vmax = 0;
for(unsigned int i = 0; i < timelist.size(); ++i)
{
average += (double)ti->first / timelist[i];
vmin = std::min<double>(vmin, (double)ti->first / timelist[i]);
vmax = std::max<double>(vmax, (double)ti->first / timelist[i]);
}
average /= timelist.size();
double variance = 0.0;
for(unsigned int i = 0; i < timelist.size(); ++i)
{
double delta = ((double)ti->first / timelist[i]) - average;
variance += delta * delta;
}
variance = variance / (timelist.size() - 1);
double stddev = std::sqrt(variance);
if (timelist.size() == 1) {
variance = stddev = 0.0;
}
of << std::setprecision(16);
of << ti->first << " " << average << " " << stddev << " " << vmin << " " << vmax << "\n";
}
of.close();
}