Project

General

Profile

Bug #9270 » main.cpp

Steven Köhler, 11/02/2021 02:54 PM

 

// includes (STL)
#include <algorithm>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
// includes (Wt)
#include <Wt/WContainerWidget.h>

#include "Timer.hpp"

using namespace Wt;

//!
//!
//!
void testUniqueness()
{
static const size_t NumTasks = 100;
static const size_t ObjectsPerTask = 100000;

// task for creating and returning a vector containing 'ObjectsPerTask' WContainerWidgets
auto createTask = []()
{
std::vector<std::unique_ptr<Wt::WContainerWidget>> result;
result.reserve(ObjectsPerTask);
for (size_t i = 0; i < ObjectsPerTask; ++i)
{
result.emplace_back(std::make_unique<Wt::WContainerWidget>());
}
return result;
};

// task for creating and returning a vector containing the string IDs of the passed WContainerWidgets
// this task also removes duplicated IDs
auto idTask = [](const std::vector<std::unique_ptr<Wt::WContainerWidget>>& ws, size_t taskId)
{
// create IDs
std::vector<std::string> result;
result.reserve(ObjectsPerTask);
for (const auto& w : ws)
{
result.emplace_back(w->id());
}
// remove duplicates that occured in the current task
std::sort(std::begin(result), std::end(result));
result.erase(std::unique(std::begin(result), std::end(result)), std::end(result));
return result;
};

std::cout << "creating widgets ...\n";
std::vector<std::future<std::vector<std::unique_ptr<Wt::WContainerWidget>>>> wfs;
wfs.reserve(NumTasks);
// spawn 'NumTasks' threads, each performing the 'createTask' task
for (size_t i = 0; i < NumTasks; ++i)
{
wfs.emplace_back(std::async(std::launch::async, createTask));
}
// wait for all tasks to finish
for (const auto& f : wfs)
{
f.wait();
}

std::cout << "creating ids ...\n";
std::vector<std::future<std::vector<std::string>>> idfs;
idfs.reserve(NumTasks);
// spawn 'NumTasks' threads, each performing the 'idTask' task for one of the results
// from previously executed 'createTask'
for (size_t i = 0; i < NumTasks; ++i)
{
idfs.emplace_back(std::async(std::launch::async, idTask, wfs[i].get(), i));
}
// wait for all tasks to finish
for (const auto& f : idfs)
{
f.wait();
}

std::cout << "merging ids & removing duplicates ...\n\n";
std::vector<std::string> ids;
ids.reserve(NumTasks * ObjectsPerTask);
for (size_t i = 0; i < NumTasks; ++i)
{
// get the string IDs for task #i
auto tmp = idfs[i].get();

// print the number of WContainerWidgets with unique IDs built in task #i
// (duplicates already removed in 'idTask')
std::cout << "task #" << i << ": " << tmp.size() << " of " << ObjectsPerTask << " ids are unique\n";

// add all IDs container for all IDs
ids.insert(std::end(ids), std::make_move_iterator(std::begin(tmp)), std::make_move_iterator(std::end(tmp)));
}

// remove all duplicated IDs that occured in any task
std::sort(std::begin(ids), std::end(ids));
ids.erase(std::unique(std::begin(ids), std::end(ids)), std::end(ids));
std::cout << "\noverall: " << ids.size() << " of " << NumTasks * ObjectsPerTask << " ids are unique\n\n";
}

//!
//!
//!
void measurePerformance()
{
static size_t N = 5000000;

double elapsed = 0;
for (size_t k = 0; k < 10; ++k)
{
std::vector<std::unique_ptr<Wt::WContainerWidget>> ws;
ws.reserve(N);

sk::tools::Timer t;
t.start();

for (size_t i = 0; i < N; ++i)
{
ws.emplace_back(std::make_unique<Wt::WContainerWidget>());
}

t.stop();
elapsed += t.elapsed();
std::cout << "elapsed time #" << k << ": " << t.elapsed() << "ms\n";
}

std::cout << "elapsed time (mean): " << elapsed / 10 << "ms\n\n";
}

//!
//!
//!
int main(int argc, char** args)
{
testUniqueness();
measurePerformance();

return 0;
}
(6-6/8)