aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-09-01 09:13:01 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-01 15:40:37 +0000
commit5f13bef50119961c8ba3698393d4afa20dd26b3e (patch)
tree028fadee36a8376f45c902d08413c989ef776957 /tools
parent4f40caf33e15c4e2e21742854dfd5cfd31812c3f (diff)
ok, rate limit forking
On Macs the user process limit is low, in the hundreds, and it's a little annoying to mysteriously find other programs fail to start because ok is greedily slurping up all the available process capacity. On Linux the user process limit is up in the ten-thousands, so I don't expect this to matter there, even on Android. I haven't seen any significant speed difference imposing a default ncpus limit. Change-Id: Id284723808074441710c0436acbd75ab1c6bbbb3 Reviewed-on: https://skia-review.googlesource.com/41840 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/ok_engines.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/tools/ok_engines.cpp b/tools/ok_engines.cpp
index e2218bfa2a..3304f3e22c 100644
--- a/tools/ok_engines.cpp
+++ b/tools/ok_engines.cpp
@@ -6,6 +6,7 @@
*/
#include "ok.h"
+#include <stdlib.h>
struct SerialEngine : Engine {
static std::unique_ptr<Engine> Factory(Options) {
@@ -44,14 +45,26 @@ static Register thread("thread",
#include <unistd.h>
struct ForkEngine : Engine {
- static std::unique_ptr<Engine> Factory(Options) {
+ int limit; // How many concurrent subprocesses do we allow to run at max?
+ int alive = 0; // How many concurrent subprocesses do we have running right now?
+
+ static std::unique_ptr<Engine> Factory(Options options) {
ForkEngine engine;
+ engine.limit = atoi(options("limit", "0").c_str());
+ if (engine.limit < 1) {
+ engine.limit = std::thread::hardware_concurrency();
+ }
return move_unique(engine);
}
bool crashproof() override { return true; }
std::future<Status> spawn(std::function<Status(void)> fn) override {
+ if (alive == limit) {
+ // The caller will wait for a child process to finish then try again.
+ return std::future<Status>();
+ }
+
switch (fork()) {
case 0:
// We are the spawned child process.
@@ -66,10 +79,12 @@ static Register thread("thread",
default:
// We succesfully spawned a child process!
// This will wait for any spawned process to finish and return its Status.
- return std::async(std::launch::deferred, [] {
+ alive++;
+ return std::async(std::launch::deferred, [&] {
do {
int status;
if (wait(&status) > 0) {
+ alive--;
return WIFEXITED(status) ? (Status)WEXITSTATUS(status)
: Status::Crashed;
}
@@ -80,6 +95,6 @@ static Register thread("thread",
}
};
static Register _fork("fork",
- "Run each task in an independent process with fork().",
+ "Run each task in an independent process with fork(), limit=ncpus.",
ForkEngine::Factory);
#endif