Skip to content

Instantly share code, notes, and snippets.

@bwedding
Last active February 21, 2018 02:03
Show Gist options
  • Save bwedding/1a9b648842608a95aedfc21c6f19f36c to your computer and use it in GitHub Desktop.
Save bwedding/1a9b648842608a95aedfc21c6f19f36c to your computer and use it in GitHub Desktop.
QConcurrent Test
#include <QtCore/QCoreApplication>
#include <QtConcurrent\qtconcurrentrun.h>
#include <qstring.h>
#include <qfuture.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <random>
#include <string>
#include <windows.h>
// ======================================================================== //
// Because this is a wee benchmark, let's save our fingers a bit. //
// ======================================================================== //
using namespace std;
static random_device rd;
static default_random_engine rng(rd());
static auto alpha = uniform_int_distribution<int>('A', 'Z');
const int INNER_LOOPS = 50; // I can't really allocate static buffers much bigger than this so I have to turn nested loops
const int TOTAL_LOOPS = 1000;
const int SPLIT_SZ = 100;
const size_t max_size = 1u << 24;
static char input_buf[INNER_LOOPS][max_size] = { 0 };
static char output_buf[max_size * 2] = { 0 };
class Timer
{
double PCFreq = 0.0;
__int64 CounterStart = 0;
public:
void StartCounter()
{
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li))
cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart) / 1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart - CounterStart) / PCFreq;
}
};
static void GenerateString(char *const buf, string& str, const size_t length)
{
// Initially fill with random alphabetic chars.
std::generate(buf, buf + length, [] { return alpha(rng); });
// Now randomly replace every ~12th character (+/-4) with a comma.
auto comma = uniform_int_distribution<int>(8, 16);
for (auto i = 0 * length; i < length; i += comma(rng))
buf[i] = ',';
buf[length] = 0;
str.reserve(length);
str = buf;
}
static string InsertNewlinesCppStyle(const string& source)
{
const auto result_len = source.size() * 2;
string result(result_len, '\n');
auto ri = begin(result);
for (const auto c : source)
{
*ri++ = c;
ri += c == ',';
}
result.erase(ri, end(result)); // Throw the rest away
return result;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Timer tm;
// Let's pick a random size between 4MB and 8MB.
auto dist = uniform_int_distribution<size_t>(1u << 22, 1u << 23);
string input_str[INNER_LOOPS]{};
QFuture<string> fut[SPLIT_SZ];
// Generate this test-case.
for (int i = 0; i < INNER_LOOPS; i++)
{
GenerateString(input_buf[i], input_str[i], dist(rng));
}
tm.StartCounter();
for (int z = 0; z < TOTAL_LOOPS / INNER_LOOPS; z++ ) // To get a total of 1000 iterations
{
for (int x = 0; x < INNER_LOOPS; x++)
{
int xx = input_str[x].length();
int parts = xx / SPLIT_SZ;
for (int i = 0, j = 0; j < SPLIT_SZ; j++, i += parts)
{
fut[j] = QtConcurrent::run(InsertNewlinesCppStyle, input_str[x].substr(i, parts));
}
string results[SPLIT_SZ], finalstring;
for (int i = 0; i < SPLIT_SZ; i++)
{
results[i] = fut[i].result();
finalstring.append(results[i]);
}
}
}
cout << "Runtime: " << tm.GetCounter()/1000.0 << " Secs" << endl;
cout << tm.GetCounter() / 1000.0 / TOTAL_LOOPS << " Seconds per iteration" << endl;
return a.exec();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment