summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2012-04-28 17:56:38 (GMT)
committerEvan Martin <martine@danga.com>2012-04-28 17:56:38 (GMT)
commit3e9cb5d72ae6ea6faab4b7bdb7781d130590e799 (patch)
tree441e526ad70f5c6c8e8afedb8fc50ed9981c6589 /src
parent8066c2d1bb5821077450755d774121e0205cb790 (diff)
parentb50f7d1f30991998564f62aa717862efb7555044 (diff)
downloadNinja-3e9cb5d72ae6ea6faab4b7bdb7781d130590e799.zip
Ninja-3e9cb5d72ae6ea6faab4b7bdb7781d130590e799.tar.gz
Ninja-3e9cb5d72ae6ea6faab4b7bdb7781d130590e799.tar.bz2
Merge pull request #274 from polrop/max_load_average
Max load average
Diffstat (limited to 'src')
-rw-r--r--src/build.cc4
-rw-r--r--src/build.h5
-rw-r--r--src/ninja.cc13
-rw-r--r--src/util.cc29
-rw-r--r--src/util.h4
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
+}
diff --git a/src/util.h b/src/util.h
index 9b4e745..399913e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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