[Libreoffice-commits] online.git: loolwsd/LOOLBroker.cpp loolwsd/LOOLKit.cpp
Michael Meeks
michael.meeks at collabora.com
Mon Apr 4 04:02:42 UTC 2016
loolwsd/LOOLBroker.cpp | 175 +++++++++++++++++++++++++++++++++++--------------
loolwsd/LOOLKit.cpp | 18 +++--
2 files changed, 137 insertions(+), 56 deletions(-)
New commits:
commit 7f13face521315bc14feb8d67056ebbe57828d49
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Fri Apr 1 20:27:14 2016 +0100
Attempt at loolbroker benchmark mode.
Change-Id: Ia1d7450b1e99686e3c654f427c231fd7e0cf8254
Reviewed-on: https://gerrit.libreoffice.org/23773
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index d79b032..ec27fa4 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -41,7 +41,7 @@ static std::string loolkitPath;
static std::atomic<unsigned> forkCounter;
static std::chrono::steady_clock::time_point lastMaintenanceTime = std::chrono::steady_clock::now();
static unsigned int childCounter = 0;
-static int numPreSpawnedChildren = 0;
+static int numPreSpawnedChildren = 1;
static std::mutex forkMutex;
@@ -202,6 +202,8 @@ public:
return false;
}
+ Log::debug("Got message from child ! '" + response + "'");
+
StringTokenizer tokens(response, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
if (tokens.count() > 0 && tokens[0] != childPid)
{
@@ -284,6 +286,16 @@ public:
Log::debug("Thread [" + thread_name + "] finished.");
}
+ bool waitForResponse()
+ {
+ std::string response;
+ if (_childPipeReader.readLine(response, [](){ return TerminationFlag; }) <= 0)
+ Log::error("Error reading response to benchmark message from child");
+ else
+ Log::debug("got response '" + response + "'");
+ return response == "started";
+ }
+
private:
IoUtil::PipeReader _childPipeReader;
};
@@ -340,7 +352,8 @@ static int createLibreOfficeKit(const bool sharePages,
const std::string& childRoot,
const std::string& sysTemplate,
const std::string& loTemplate,
- const std::string& loSubPath)
+ const std::string& loSubPath,
+ bool doBenchmark)
{
Process::PID childPID;
int fifoWriter = -1;
@@ -370,7 +383,7 @@ static int createLibreOfficeKit(const bool sharePages,
Thread::sleep(std::stoul(std::getenv("SLEEPKITFORDEBUGGER")) * 1000);
}
- lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit);
+ lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit, doBenchmark);
_exit(Application::EXIT_OK);
}
else
@@ -487,6 +500,78 @@ static bool waitForTerminationChild(const Process::PID pid, int count = CHILD_TI
return false;
}
+static void printArgumentHelp()
+{
+ std::cout << "Usage: loolbroker [OPTION]..." << std::endl;
+ std::cout << " Single threaded process broker that spawns lok instances" << std::endl;
+ std::cout << " note: running this standalone is not possible, it is spawned by the loolwsd" << std::endl;
+ std::cout << " and is controlled via a pipe." << std::endl;
+ std::cout << "" << std::endl;
+ std::cout << " Some parameters are required and passed on to the lok instance:" << std::endl;
+ std::cout << " --losubpath=<path> path to chroot for child to live inside." << std::endl;
+ std::cout << " --childroot=<path> path to chroot for child to live inside." << std::endl;
+ std::cout << " --systemplate=<path> path of system template to pre-populate chroot with." << std::endl;
+ std::cout << " --lotemplate=<path> path of libreoffice template to pre-populate chroot with." << std::endl;
+ std::cout << " --pipe=<path> path of loolwsd pipe to connect to on startup." << std::endl;
+ std::cout << " --losubpath=<path> path to libreoffice install" << std::endl;
+ std::cout << "" << std::endl;
+ std::cout << " Some paramaters are optional:" << std::endl;
+ std::cout << " --numprespawns=<number> pre-fork at least <number> processes [1]" << std::endl;
+ std::cout << " --benchmark pre-fork processes, and print statistics before exiting" << std::endl;
+}
+
+void setupPipes(const std::string &childRoot, bool doBenchmark)
+{
+ const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
+ if (!doBenchmark)
+ {
+ const std::string pipeLoolwsd = Path(pipePath, FIFO_LOOLWSD).toString();
+ if ( (readerBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
+ {
+ Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read only. Exiting.");
+ std::exit(Application::EXIT_SOFTWARE);
+ }
+ }
+
+ int pipeFlags = O_RDONLY | O_NONBLOCK;
+ const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
+ if (mkfifo(pipeBroker.c_str(), 0666) < 0 && errno != EEXIST)
+ {
+ Log::error("Error: Failed to create pipe FIFO [" + FIFO_BROKER + "].");
+ std::exit(Application::EXIT_SOFTWARE);
+ }
+
+ if ((readerChild = open(pipeBroker.c_str(), pipeFlags) ) < 0)
+ {
+ Log::error("Error: pipe opened for reading.");
+ std::exit(Application::EXIT_SOFTWARE);
+ }
+
+ if ((pipeFlags = fcntl(readerChild, F_GETFL, 0)) < 0)
+ {
+ Log::error("Error: failed to get pipe flags [" + FIFO_BROKER + "].");
+ std::exit(Application::EXIT_SOFTWARE);
+ }
+
+ pipeFlags &= ~O_NONBLOCK;
+ if (fcntl(readerChild, F_SETFL, pipeFlags) < 0)
+ {
+ Log::error("Error: failed to set pipe flags [" + FIFO_BROKER + "].");
+ std::exit(Application::EXIT_SOFTWARE);
+ }
+
+ if (!doBenchmark)
+ {
+ // Open notify pipe
+ const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
+ if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+ {
+ Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + "] for writing.");
+ exit(Application::EXIT_SOFTWARE);
+ }
+ }
+}
+
// Broker process
int main(int argc, char** argv)
{
@@ -508,6 +593,7 @@ int main(int argc, char** argv)
std::string loSubPath;
std::string sysTemplate;
std::string loTemplate;
+ bool doBenchmark = false;
for (int i = 0; i < argc; ++i)
{
@@ -543,22 +629,18 @@ int main(int argc, char** argv)
eq = std::strchr(cmd, '=');
ClientPortNumber = std::stoll(std::string(eq+1));
}
+ else if (std::strstr(cmd, "--benchmark"))
+ doBenchmark = true;
}
loolkitPath = Poco::Path(argv[0]).parent().toString() + "loolkit";
- assert(!loSubPath.empty());
- assert(!sysTemplate.empty());
- assert(!loTemplate.empty());
- assert(!childRoot.empty());
- assert(numPreSpawnedChildren >= 1);
-
- const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
- const std::string pipeLoolwsd = Path(pipePath, FIFO_LOOLWSD).toString();
- if ( (readerBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
+ if (loSubPath.empty() || sysTemplate.empty() ||
+ loTemplate.empty() || childRoot.empty() ||
+ numPreSpawnedChildren < 1)
{
- Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read only. Exiting.");
- std::exit(Application::EXIT_SOFTWARE);
+ printArgumentHelp();
+ return 1;
}
if (!std::getenv("LD_BIND_NOW"))
@@ -567,40 +649,7 @@ int main(int argc, char** argv)
if (!std::getenv("LOK_VIEW_CALLBACK"))
Log::info("Note: LOK_VIEW_CALLBACK is not set.");
- int pipeFlags = O_RDONLY | O_NONBLOCK;
- const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
- if (mkfifo(pipeBroker.c_str(), 0666) < 0 && errno != EEXIST)
- {
- Log::error("Error: Failed to create pipe FIFO [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- if ((readerChild = open(pipeBroker.c_str(), pipeFlags) ) < 0)
- {
- Log::error("Error: pipe opened for reading.");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- if ((pipeFlags = fcntl(readerChild, F_GETFL, 0)) < 0)
- {
- Log::error("Error: failed to get pipe flags [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- pipeFlags &= ~O_NONBLOCK;
- if (fcntl(readerChild, F_SETFL, pipeFlags) < 0)
- {
- Log::error("Error: failed to set pipe flags [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- // Open notify pipe
- const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
- if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
- {
- Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + "] for writing.");
- exit(Application::EXIT_SOFTWARE);
- }
+ setupPipes(childRoot, doBenchmark);
// Initialize LoKit and hope we can fork and save memory by sharing pages.
const bool sharePages = std::getenv("LOK_NO_PREINIT") == nullptr
@@ -614,7 +663,7 @@ int main(int argc, char** argv)
// We must have at least one child, more is created dynamically.
if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
- loTemplate, loSubPath) < 0)
+ loTemplate, loSubPath, doBenchmark) < 0)
{
Log::error("Error: failed to create children.");
std::exit(Application::EXIT_SOFTWARE);
@@ -637,6 +686,8 @@ int main(int argc, char** argv)
Log::info("loolbroker is ready.");
+ Poco::Timestamp startTime;
+
int childExitCode = EXIT_SUCCESS;
unsigned timeoutCounter = 0;
while (!TerminationFlag)
@@ -741,7 +792,7 @@ int main(int argc, char** argv)
do
{
if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
- loTemplate, loSubPath) < 0)
+ loTemplate, loSubPath, doBenchmark) < 0)
{
Log::error("Error: fork failed.");
}
@@ -770,6 +821,30 @@ int main(int argc, char** argv)
childExitCode = EXIT_SUCCESS;
sleep(MAINTENANCE_INTERVAL);
}
+
+ if (doBenchmark)
+ break;
+ }
+
+ if (doBenchmark)
+ {
+ Log::info("loolbroker benchmark - waiting for kits.");
+
+ int numSpawned = 0;
+ while (numSpawned < numPreSpawnedChildren)
+ {
+ if (pipeHandler.waitForResponse())
+ numSpawned++;
+ Log::info("got children " + std::to_string(numSpawned));
+ }
+
+ sleep (10);
+
+ Poco::Timestamp::TimeDiff elapsed = startTime.elapsed();
+ std::cerr << "Time to launch " << numPreSpawnedChildren << " children: " << (1.0 * elapsed)/Poco::Timestamp::resolution() << std::endl;
+ Log::info("loolbroker benchmark complete.");
+
+ TerminationFlag = true;
}
// Terminate child processes.
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 620a40b..23c498f 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -807,7 +807,8 @@ void lokit_main(const std::string& childRoot,
const std::string& sysTemplate,
const std::string& loTemplate,
const std::string& loSubPath,
- const std::string& pipe)
+ const std::string& pipe,
+ bool doBenchmark = false)
{
#ifdef LOOLKIT_NO_MAIN
// Reinitialize logging when forked.
@@ -859,12 +860,15 @@ void lokit_main(const std::string& childRoot,
std::exit(Application::EXIT_SOFTWARE);
}
- // Open notify pipe
- const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
- if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+ if (!doBenchmark)
{
- Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + "] for writing.");
- exit(Application::EXIT_SOFTWARE);
+ // Open notify pipe
+ const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
+ if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+ {
+ Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + "] for writing.");
+ exit(Application::EXIT_SOFTWARE);
+ }
}
const Path jailPath = Path::forDirectory(childRoot + Path::separator() + jailId);
@@ -953,6 +957,8 @@ void lokit_main(const std::string& childRoot,
}
Log::info("loolkit [" + std::to_string(Process::id()) + "] is ready.");
+ if (doBenchmark)
+ IoUtil::writeFIFO(writerBroker, "started\n");
char buffer[READ_BUFFER_SIZE];
std::string message;
More information about the Libreoffice-commits
mailing list