Use boost-asio to improve FAIL* server performance

This patch overhauls the FAIL* server code to leverage Boost asio to be able to
handle a large number of clients (>4000). In this implementation the server is
now single threaded. I've not encountered any problems with this for up to
about 10k clients. Boost ASIO can also be used multithreaded, but I assume the
FAIL* internal data structures (Synchronized*) will become a bottleneck first.

The code now additionally depends on Boost Coro and Boost Context, as well as
a C++ 14 compiler, although the only C++14 feature required is a lambda capture
with initializer, such as [ x = std::move(x) ]. gcc-4.9.2 does this.

The code could (and probably should) be cleaned up more. Comments are wordy,
code is unnecessary now (multiple server threads), code is not self-contained
(headers spread dependencies), many ifdef's (server performance measuring
should be runtime rather than a compile time option), and much more. But for
this patch I was going for a minimal changeset the get the functionality in,
to have an easier review. Alas, FAIL* has no Unit-test suite to run the changes
against.

To handle such a large number of clients more changes were necessary, for
example server status output is now performed every 1s, instead for every
request.

The class Minion was removed completely; the only thing it was doing was
encapsulate an int.

The server has now a runtime-configurable port, or it can select a free port on
its own if none is specified. This requires the CampaignManager to add a port
argument and instantiate the JobServer dynamically.

Change-Id: Iad9238972161f95f5802bd2251116f8aeee14884
This commit is contained in:
Hannes Weisbach
2017-05-22 14:19:13 +02:00
parent 48ceeb6a14
commit 6c120004eb
7 changed files with 345 additions and 302 deletions

View File

@ -1,7 +1,46 @@
#include <cstdlib>
#include "CampaignManager.hpp"
#include "util/Logger.hpp"
#include "JobServer.hpp"
namespace fail {
static Logger log_send("CampaignManager");
CampaignManager campaignmanager;
CampaignManager::~CampaignManager() { delete m_jobserver; }
bool CampaignManager::runCampaign(Campaign *c) {
fail::CommandLine &cmd = fail::CommandLine::Inst();
if (!cmd.parse()) {
log_send << "Error parsing arguments." << std::endl;
exit(-1);
}
if (!m_jobserver) {
m_jobserver = (cmd[port].count() > 0)
? new JobServer(std::atoi(cmd[port].first()->arg))
: new JobServer;
}
m_currentCampaign = c;
bool ret = c->run();
m_jobserver->done();
return ret;
}
void CampaignManager::addParam(ExperimentData *exp)
{
m_jobserver->addParam(exp);
}
ExperimentData *CampaignManager::getDone() { return m_jobserver->getDone(); }
void CampaignManager::noMoreParameters()
{
m_jobserver->setNoMoreExperiments();
}
void CampaignManager::done() { m_jobserver->done(); }
} // end-of-namespace: fail