authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-19 16:21:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:12-07:00
logcb094700631ea1ae238ea678c192ce4f85fbecc0
treeb79eb3a4bd26ce880829be3665470c3049d0fe53
parent96d798db8b704a2fd367e58a19d6fe853a8a76a8

zig build: add a -j<N> option for limiting concurrency


3 files changed, 29 insertions(+), 6 deletions(-)

lib/build_runner.zig+18-2
......@@ -87,6 +87,7 @@ pub fn main() !void {
8787
8888 var targets = ArrayList([]const u8).init(allocator);
8989 var debug_log_scopes = ArrayList([]const u8).init(allocator);
90 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = allocator };
9091
9192 const stderr_stream = io.getStdErr().writer();
9293 const stdout_stream = io.getStdOut().writer();
......@@ -231,6 +232,19 @@ pub fn main() !void {
231232 };
232233 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
233234 builder.reference_trace = null;
235 } else if (mem.startsWith(u8, arg, "-j")) {
236 const num = arg["-j".len..];
237 const n_jobs = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
238 std.debug.print("unable to parse jobs count '{s}': {s}", .{
239 num, @errorName(err),
240 });
241 process.exit(1);
242 };
243 if (n_jobs < 1) {
244 std.debug.print("number of jobs must be at least 1\n", .{});
245 process.exit(1);
246 }
247 thread_pool_options.n_jobs = n_jobs;
234248 } else if (mem.eql(u8, arg, "--")) {
235249 builder.args = argsRest(args, arg_idx);
236250 break;
......@@ -258,7 +272,7 @@ pub fn main() !void {
258272 if (builder.validateUserInputDidItFail())
259273 usageAndErr(builder, true, stderr_stream);
260274
261 runStepNames(builder, targets.items, main_progress_node) catch |err| {
275 runStepNames(builder, targets.items, main_progress_node, thread_pool_options) catch |err| {
262276 switch (err) {
263277 error.UncleanExit => process.exit(1),
264278 else => return err,
......@@ -270,6 +284,7 @@ fn runStepNames(
270284 b: *std.Build,
271285 step_names: []const []const u8,
272286 parent_prog_node: *std.Progress.Node,
287 thread_pool_options: std.Thread.Pool.Options,
273288) !void {
274289 var step_stack = ArrayList(*Step).init(b.allocator);
275290 defer step_stack.deinit();
......@@ -297,7 +312,7 @@ fn runStepNames(
297312 }
298313
299314 var thread_pool: std.Thread.Pool = undefined;
300 try thread_pool.init(b.allocator);
315 try thread_pool.init(thread_pool_options);
301316 defer thread_pool.deinit();
302317
303318 {
......@@ -523,6 +538,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
523538 \\ --verbose Print commands before executing them
524539 \\ --color [auto|off|on] Enable or disable colored error messages
525540 \\ --prominent-compile-errors Output compile errors formatted for a human to read
541 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
526542 \\
527543 \\Project-Specific Options:
528544 \\
lib/std/Thread/Pool.zig+9-2
......@@ -17,7 +17,14 @@ const Runnable = struct {
1717
1818const RunProto = *const fn (*Runnable) void;
1919
20pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {
20pub const Options = struct {
21 allocator: std.mem.Allocator,
22 n_jobs: ?u32 = null,
23};
24
25pub fn init(pool: *Pool, options: Options) !void {
26 const allocator = options.allocator;
27
2128 pool.* = .{
2229 .allocator = allocator,
2330 .threads = &[_]std.Thread{},
......@@ -27,7 +34,7 @@ pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {
2734 return;
2835 }
2936
30 const thread_count = std.math.max(1, std.Thread.getCpuCount() catch 1);
37 const thread_count = options.n_jobs orelse @max(1, std.Thread.getCpuCount() catch 1);
3138 pool.threads = try allocator.alloc(std.Thread, thread_count);
3239 errdefer allocator.free(pool.threads);
3340
src/main.zig+2-2
......@@ -2999,7 +2999,7 @@ fn buildOutputType(
29992999 defer zig_lib_directory.handle.close();
30003000
30013001 var thread_pool: ThreadPool = undefined;
3002 try thread_pool.init(gpa);
3002 try thread_pool.init(.{ .allocator = gpa });
30033003 defer thread_pool.deinit();
30043004
30053005 var libc_installation: ?LibCInstallation = null;
......@@ -4201,7 +4201,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
42014201 .basename = exe_basename,
42024202 };
42034203 var thread_pool: ThreadPool = undefined;
4204 try thread_pool.init(gpa);
4204 try thread_pool.init(.{ .allocator = gpa });
42054205 defer thread_pool.deinit();
42064206
42074207 var cleanup_build_runner_dir: ?fs.Dir = null;