diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.cc | 4 | ||||
-rw-r--r-- | src/build.h | 5 | ||||
-rw-r--r-- | src/ninja.cc | 13 | ||||
-rw-r--r-- | src/util.cc | 29 | ||||
-rw-r--r-- | src/util.h | 4 |
5 files changed, 51 insertions, 4 deletions
diff --git a/src/build.cc b/src/build.cc index a9e1e56..03a9d0d 100644 --- a/src/build.cc +++ b/src/build.cc @@ -474,7 +474,9 @@ void RealCommandRunner::Abort() { } bool RealCommandRunner::CanRunMore() { - return ((int)subprocs_.running_.size()) < config_.parallelism; + return ((int)subprocs_.running_.size()) < config_.parallelism + && ((subprocs_.running_.size() == 0 || config_.max_load_average <= 0.0f) + || GetLoadAverage() < config_.max_load_average); } bool RealCommandRunner::StartCommand(Edge* edge) { diff --git a/src/build.h b/src/build.h index c0328f3..407aecc 100644 --- a/src/build.h +++ b/src/build.h @@ -99,7 +99,7 @@ struct CommandRunner { /// Options (e.g. verbosity, parallelism) passed to a build. struct BuildConfig { BuildConfig() : verbosity(NORMAL), dry_run(false), parallelism(1), - failures_allowed(1) {} + failures_allowed(1), max_load_average(-0.0f) {} enum Verbosity { NORMAL, @@ -110,6 +110,9 @@ struct BuildConfig { bool dry_run; int parallelism; int failures_allowed; + /// The maximum load average we must not exceed. A negative value + /// means that we do not have any limit. + double max_load_average; }; /// Builder wraps the build process: starting commands, updating status. diff --git a/src/ninja.cc b/src/ninja.cc index 8b91a12..ac862e9 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -85,6 +85,7 @@ void Usage(const BuildConfig& config) { " -f FILE specify input build file [default=build.ninja]\n" "\n" " -j N run N jobs in parallel [default=%d]\n" +" -l N do not start new jobs if the load average is greater than N\n" " -k N keep going until N jobs fail [default=1]\n" " -n dry run (don't run commands but pretend they succeeded)\n" " -v show all command lines while building\n" @@ -640,7 +641,7 @@ int main(int argc, char** argv) { int opt; while (tool.empty() && - (opt = getopt_long(argc, argv, "d:f:hj:k:nt:vC:", kLongOptions, + (opt = getopt_long(argc, argv, "d:f:hj:k:l:nt:vC:", kLongOptions, NULL)) != -1) { switch (opt) { case 'd': @@ -653,11 +654,19 @@ int main(int argc, char** argv) { case 'j': globals.config.parallelism = atoi(optarg); break; + case 'l': { + char* end; + double value = strtod(optarg, &end); + if (end == optarg) + Fatal("-l parameter not numeric: did you mean -l 0.0?"); + globals.config.max_load_average = value; + break; + } case 'k': { char* end; int value = strtol(optarg, &end, 10); if (*end != 0) - Fatal("-k parameter not numeric; did you mean -k0?"); + Fatal("-k parameter not numeric; did you mean -k 0?"); // We want to go until N jobs fail, which means we should allow // N failures and then stop. For N <= 0, INT_MAX is close enough diff --git a/src/util.cc b/src/util.cc index c88dc4e..73f13f8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -293,3 +293,32 @@ string StripAnsiEscapeCodes(const string& in) { } return stripped; } + +#ifdef _WIN32 +static double GetLoadAverage_win32() +{ + // TODO(nicolas.despres@gmail.com): Find a way to implement it on Windows. + return -0.0f; +} +#else +static double GetLoadAverage_unix() +{ + double loadavg[3] = { 0.0f, 0.0f, 0.0f }; + if (getloadavg(loadavg, 3) < 0) + { + // Maybe we should return an error here or the availability of + // getloadavg(3) should be checked when ninja is configured. + return -0.0f; + } + return loadavg[0]; +} +#endif // _WIN32 + +double GetLoadAverage() +{ +#ifdef _WIN32 + return GetLoadAverage_win32(); +#else + return GetLoadAverage_unix(); +#endif // _WIN32 +} @@ -68,6 +68,10 @@ const char* SpellcheckString(const string& text, ...); /// Removes all Ansi escape codes (http://www.termsys.demon.co.uk/vtansi.htm). string StripAnsiEscapeCodes(const string& in); +/// @return the load average of the machine. A negative value is returned +/// on error. +double GetLoadAverage(); + #ifdef _MSC_VER #define snprintf _snprintf #define fileno _fileno |