Merge pull request #274 from polrop/max_load_average

Max load average
This commit is contained in:
Evan Martin 2012-04-28 10:56:38 -07:00
commit 3e9cb5d72a
5 changed files with 51 additions and 4 deletions

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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
}

View File

@ -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