diff options
author | Jan Niklas Hasse <jhasse@bixense.com> | 2024-02-29 17:59:19 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 17:59:19 (GMT) |
commit | bf6409ad5aa0c92db0add01c959e276fdcc7fc23 (patch) | |
tree | 3059c3e5170712df29f2345a69bf715b5969fd57 /src | |
parent | 460dff81192617168ea05eae0b7816054f2aa32d (diff) | |
parent | 8a2575e432b85baecb0054cc570db69f074c2633 (diff) | |
download | Ninja-bf6409ad5aa0c92db0add01c959e276fdcc7fc23.zip Ninja-bf6409ad5aa0c92db0add01c959e276fdcc7fc23.tar.gz Ninja-bf6409ad5aa0c92db0add01c959e276fdcc7fc23.tar.bz2 |
Merge pull request #1949 from Flowdalic/load-capacity
Consider the remaining job capacity in main loop
Diffstat (limited to 'src')
-rw-r--r-- | src/build.cc | 55 | ||||
-rw-r--r-- | src/build.h | 2 | ||||
-rw-r--r-- | src/build_test.cc | 11 |
3 files changed, 51 insertions, 17 deletions
diff --git a/src/build.cc b/src/build.cc index e0c3939..9c5cb66 100644 --- a/src/build.cc +++ b/src/build.cc @@ -18,6 +18,8 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <climits> +#include <stdint.h> #include <functional> #if defined(__SVR4) && defined(__sun) @@ -46,7 +48,7 @@ struct DryRunCommandRunner : public CommandRunner { virtual ~DryRunCommandRunner() {} // Overridden from CommandRunner: - virtual bool CanRunMore() const; + virtual size_t CanRunMore() const; virtual bool StartCommand(Edge* edge); virtual bool WaitForCommand(Result* result); @@ -54,8 +56,8 @@ struct DryRunCommandRunner : public CommandRunner { queue<Edge*> finished_; }; -bool DryRunCommandRunner::CanRunMore() const { - return true; +size_t DryRunCommandRunner::CanRunMore() const { + return SIZE_MAX; } bool DryRunCommandRunner::StartCommand(Edge* edge) { @@ -569,7 +571,7 @@ void Plan::Dump() const { struct RealCommandRunner : public CommandRunner { explicit RealCommandRunner(const BuildConfig& config) : config_(config) {} virtual ~RealCommandRunner() {} - virtual bool CanRunMore() const; + virtual size_t CanRunMore() const; virtual bool StartCommand(Edge* edge); virtual bool WaitForCommand(Result* result); virtual vector<Edge*> GetActiveEdges(); @@ -592,12 +594,26 @@ void RealCommandRunner::Abort() { subprocs_.Clear(); } -bool RealCommandRunner::CanRunMore() const { +size_t RealCommandRunner::CanRunMore() const { size_t subproc_number = subprocs_.running_.size() + subprocs_.finished_.size(); - return (int)subproc_number < config_.parallelism - && ((subprocs_.running_.empty() || config_.max_load_average <= 0.0f) - || GetLoadAverage() < config_.max_load_average); + + int64_t capacity = config_.parallelism - subproc_number; + + if (config_.max_load_average > 0.0f) { + int load_capacity = config_.max_load_average - GetLoadAverage(); + if (load_capacity < capacity) + capacity = load_capacity; + } + + if (capacity < 0) + capacity = 0; + + if (capacity == 0 && subprocs_.running_.empty()) + // Ensure that we make progress. + capacity = 1; + + return capacity; } bool RealCommandRunner::StartCommand(Edge* edge) { @@ -749,8 +765,13 @@ bool Builder::Build(string* err) { // Second, we attempt to wait for / reap the next finished command. while (plan_.more_to_do()) { // See if we can start any more commands. - if (failures_allowed && command_runner_->CanRunMore()) { - if (Edge* edge = plan_.FindWork()) { + if (failures_allowed) { + size_t capacity = command_runner_->CanRunMore(); + while (capacity > 0) { + Edge* edge = plan_.FindWork(); + if (!edge) + break; + if (edge->GetBindingBool("generator")) { scan_.build_log()->Close(); } @@ -769,11 +790,19 @@ bool Builder::Build(string* err) { } } else { ++pending_commands; - } - // We made some progress; go back to the main loop. - continue; + --capacity; + + // Re-evaluate capacity. + size_t current_capacity = command_runner_->CanRunMore(); + if (current_capacity < capacity) + capacity = current_capacity; + } } + + // We are finished with all work items and have no pending + // commands. Therefore, break out of the main loop. + if (pending_commands == 0 && !plan_.more_to_do()) break; } // See if we can reap any finished commands. diff --git a/src/build.h b/src/build.h index 2885f41..471f0b2 100644 --- a/src/build.h +++ b/src/build.h @@ -145,7 +145,7 @@ private: /// RealCommandRunner is an implementation that actually runs commands. struct CommandRunner { virtual ~CommandRunner() {} - virtual bool CanRunMore() const = 0; + virtual size_t CanRunMore() const = 0; virtual bool StartCommand(Edge* edge) = 0; /// The result of waiting for a command. diff --git a/src/build_test.cc b/src/build_test.cc index 71bf55c..c9cc647 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -15,6 +15,8 @@ #include "build.h" #include <assert.h> +#include <climits> +#include <stdint.h> #include "build_log.h" #include "deps_log.h" @@ -519,7 +521,7 @@ struct FakeCommandRunner : public CommandRunner { max_active_edges_(1), fs_(fs) {} // CommandRunner impl - virtual bool CanRunMore() const; + virtual size_t CanRunMore() const; virtual bool StartCommand(Edge* edge); virtual bool WaitForCommand(Result* result); virtual vector<Edge*> GetActiveEdges(); @@ -620,8 +622,11 @@ void BuildTest::RebuildTarget(const string& target, const char* manifest, builder.command_runner_.release(); } -bool FakeCommandRunner::CanRunMore() const { - return active_edges_.size() < max_active_edges_; +size_t FakeCommandRunner::CanRunMore() const { + if (active_edges_.size() < max_active_edges_) + return SIZE_MAX; + + return 0; } bool FakeCommandRunner::StartCommand(Edge* edge) { |