Merge pull request #15490 from kcbanner/skip_oom_steps

build_runner: add --skip-oom-steps
This commit is contained in:
Andrew Kelley 2023-09-22 15:09:46 -07:00 committed by GitHub
commit 0710314de6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 13 deletions

View File

@ -93,6 +93,7 @@ pub fn main() !void {
var dir_list = std.Build.DirList{};
var summary: ?Summary = null;
var max_rss: usize = 0;
var skip_oom_steps: bool = false;
var color: Color = .auto;
const stderr_stream = io.getStdErr().writer();
@ -158,6 +159,8 @@ pub fn main() !void {
});
process.exit(1);
};
} else if (mem.eql(u8, arg, "--skip-oom-steps")) {
skip_oom_steps = true;
} else if (mem.eql(u8, arg, "--search-prefix")) {
const search_prefix = nextArg(args, &arg_idx) orelse {
std.debug.print("Expected argument after {s}\n\n", .{arg});
@ -305,6 +308,7 @@ pub fn main() !void {
.max_rss = max_rss,
.max_rss_is_default = false,
.max_rss_mutex = .{},
.skip_oom_steps = skip_oom_steps,
.memory_blocked_steps = std.ArrayList(*Step).init(arena),
.claimed_rss = 0,
@ -335,6 +339,7 @@ const Run = struct {
max_rss: usize,
max_rss_is_default: bool,
max_rss_mutex: std.Thread.Mutex,
skip_oom_steps: bool,
memory_blocked_steps: std.ArrayList(*Step),
claimed_rss: usize,
@ -383,10 +388,14 @@ fn runStepNames(
for (step_stack.keys()) |s| {
if (s.max_rss == 0) continue;
if (s.max_rss > run.max_rss) {
std.debug.print("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory\n", .{
s.owner.dep_prefix, s.name, s.max_rss, run.max_rss,
});
any_problems = true;
if (run.skip_oom_steps) {
s.state = .skipped_oom;
} else {
std.debug.print("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory\n", .{
s.owner.dep_prefix, s.name, s.max_rss, run.max_rss,
});
any_problems = true;
}
}
}
if (any_problems) {
@ -416,6 +425,7 @@ fn runStepNames(
const steps_slice = step_stack.keys();
for (0..steps_slice.len) |i| {
const step = steps_slice[steps_slice.len - i - 1];
if (step.state == .skipped_oom) continue;
wait_group.start();
thread_pool.spawn(workerMakeOneStep, .{
@ -461,7 +471,7 @@ fn runStepNames(
},
.dependency_failure => pending_count += 1,
.success => success_count += 1,
.skipped => skipped_count += 1,
.skipped, .skipped_oom => skipped_count += 1,
.failure => {
failure_count += 1;
const compile_errors_len = s.result_error_bundle.errorMessageCount();
@ -506,7 +516,7 @@ fn runStepNames(
var print_node: PrintNode = .{ .parent = null };
if (step_names.len == 0) {
print_node.last = true;
printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
printTreeStep(b, b.default_step, run, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
} else {
const last_index = if (!failures_only) b.top_level_steps.count() else blk: {
var i: usize = step_names.len;
@ -519,7 +529,7 @@ fn runStepNames(
for (step_names, 0..) |step_name, i| {
const tls = b.top_level_steps.get(step_name).?;
print_node.last = i + 1 == last_index;
printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
printTreeStep(b, &tls.step, run, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
}
}
}
@ -567,6 +577,7 @@ fn printPrefix(node: *PrintNode, stderr: std.fs.File, ttyconf: std.io.tty.Config
fn printTreeStep(
b: *std.Build,
s: *Step,
run: *const Run,
stderr: std.fs.File,
ttyconf: std.io.tty.Config,
parent_node: *PrintNode,
@ -654,13 +665,18 @@ fn printTreeStep(
}
try stderr.writeAll("\n");
},
.skipped => {
.skipped, .skipped_oom => |skip| {
try ttyconf.setColor(stderr, .yellow);
try stderr.writeAll(" skipped\n");
try stderr.writeAll(" skipped");
if (skip == .skipped_oom) {
try stderr.writeAll(" (not enough memory)");
try ttyconf.setColor(stderr, .dim);
try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
try ttyconf.setColor(stderr, .yellow);
}
try stderr.writeAll("\n");
try ttyconf.setColor(stderr, .reset);
},
.failure => {
if (s.result_error_bundle.errorMessageCount() > 0) {
try ttyconf.setColor(stderr, .red);
@ -718,7 +734,7 @@ fn printTreeStep(
.parent = parent_node,
.last = i == last_index,
};
try printTreeStep(b, dep, stderr, ttyconf, &print_node, step_stack, failures_only);
try printTreeStep(b, dep, run, stderr, ttyconf, &print_node, step_stack, failures_only);
}
} else {
if (s.dependencies.items.len == 0) {
@ -767,6 +783,7 @@ fn checkForDependencyLoop(
.success => unreachable,
.failure => unreachable,
.skipped => unreachable,
.skipped_oom => unreachable,
}
}
@ -786,7 +803,7 @@ fn workerMakeOneStep(
for (s.dependencies.items) |dep| {
switch (@atomicLoad(Step.State, &dep.state, .SeqCst)) {
.success, .skipped => continue,
.failure, .dependency_failure => {
.failure, .dependency_failure, .skipped_oom => {
@atomicStore(Step.State, &s.state, .dependency_failure, .SeqCst);
return;
},
@ -979,6 +996,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
\\ none Do not print the build summary
\\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
\\ --maxrss <bytes> Limit memory usage (default is to use available memory)
\\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
\\
\\Project-Specific Options:
\\

View File

@ -70,6 +70,9 @@ pub const State = enum {
/// This state indicates that the step did not complete, however, it also did not fail,
/// and it is safe to continue executing its dependencies.
skipped,
/// This step was skipped because it specified a max_rss that exceeded the runner's maximum.
/// It is not safe to run its dependencies.
skipped_oom,
};
pub const Id = enum {