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 {...@@ -87,6 +87,7 @@ pub fn main() !void {
8787
88 var targets = ArrayList([]const u8).init(allocator);88 var targets = ArrayList([]const u8).init(allocator);
89 var debug_log_scopes = ArrayList([]const u8).init(allocator);89 var debug_log_scopes = ArrayList([]const u8).init(allocator);
90 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = allocator };
9091
91 const stderr_stream = io.getStdErr().writer();92 const stderr_stream = io.getStdErr().writer();
92 const stdout_stream = io.getStdOut().writer();93 const stdout_stream = io.getStdOut().writer();
...@@ -231,6 +232,19 @@ pub fn main() !void {...@@ -231,6 +232,19 @@ pub fn main() !void {
231 };232 };
232 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {233 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
233 builder.reference_trace = null;234 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;
234 } else if (mem.eql(u8, arg, "--")) {248 } else if (mem.eql(u8, arg, "--")) {
235 builder.args = argsRest(args, arg_idx);249 builder.args = argsRest(args, arg_idx);
236 break;250 break;
...@@ -258,7 +272,7 @@ pub fn main() !void {...@@ -258,7 +272,7 @@ pub fn main() !void {
258 if (builder.validateUserInputDidItFail())272 if (builder.validateUserInputDidItFail())
259 usageAndErr(builder, true, stderr_stream);273 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| {
262 switch (err) {276 switch (err) {
263 error.UncleanExit => process.exit(1),277 error.UncleanExit => process.exit(1),
264 else => return err,278 else => return err,
...@@ -270,6 +284,7 @@ fn runStepNames(...@@ -270,6 +284,7 @@ fn runStepNames(
270 b: *std.Build,284 b: *std.Build,
271 step_names: []const []const u8,285 step_names: []const []const u8,
272 parent_prog_node: *std.Progress.Node,286 parent_prog_node: *std.Progress.Node,
287 thread_pool_options: std.Thread.Pool.Options,
273) !void {288) !void {
274 var step_stack = ArrayList(*Step).init(b.allocator);289 var step_stack = ArrayList(*Step).init(b.allocator);
275 defer step_stack.deinit();290 defer step_stack.deinit();
...@@ -297,7 +312,7 @@ fn runStepNames(...@@ -297,7 +312,7 @@ fn runStepNames(
297 }312 }
298313
299 var thread_pool: std.Thread.Pool = undefined;314 var thread_pool: std.Thread.Pool = undefined;
300 try thread_pool.init(b.allocator);315 try thread_pool.init(thread_pool_options);
301 defer thread_pool.deinit();316 defer thread_pool.deinit();
302317
303 {318 {
...@@ -523,6 +538,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi...@@ -523,6 +538,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
523 \\ --verbose Print commands before executing them538 \\ --verbose Print commands before executing them
524 \\ --color [auto|off|on] Enable or disable colored error messages539 \\ --color [auto|off|on] Enable or disable colored error messages
525 \\ --prominent-compile-errors Output compile errors formatted for a human to read540 \\ --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)
526 \\542 \\
527 \\Project-Specific Options:543 \\Project-Specific Options:
528 \\544 \\
lib/std/Thread/Pool.zig+9-2
...@@ -17,7 +17,14 @@ const Runnable = struct {...@@ -17,7 +17,14 @@ const Runnable = struct {
1717
18const RunProto = *const fn (*Runnable) void;18const 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
21 pool.* = .{28 pool.* = .{
22 .allocator = allocator,29 .allocator = allocator,
23 .threads = &[_]std.Thread{},30 .threads = &[_]std.Thread{},
...@@ -27,7 +34,7 @@ pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {...@@ -27,7 +34,7 @@ pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {
27 return;34 return;
28 }35 }
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);
31 pool.threads = try allocator.alloc(std.Thread, thread_count);38 pool.threads = try allocator.alloc(std.Thread, thread_count);
32 errdefer allocator.free(pool.threads);39 errdefer allocator.free(pool.threads);
3340
src/main.zig+2-2
...@@ -2999,7 +2999,7 @@ fn buildOutputType(...@@ -2999,7 +2999,7 @@ fn buildOutputType(
2999 defer zig_lib_directory.handle.close();2999 defer zig_lib_directory.handle.close();
30003000
3001 var thread_pool: ThreadPool = undefined;3001 var thread_pool: ThreadPool = undefined;
3002 try thread_pool.init(gpa);3002 try thread_pool.init(.{ .allocator = gpa });
3003 defer thread_pool.deinit();3003 defer thread_pool.deinit();
30043004
3005 var libc_installation: ?LibCInstallation = null;3005 var libc_installation: ?LibCInstallation = null;
...@@ -4201,7 +4201,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -4201,7 +4201,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
4201 .basename = exe_basename,4201 .basename = exe_basename,
4202 };4202 };
4203 var thread_pool: ThreadPool = undefined;4203 var thread_pool: ThreadPool = undefined;
4204 try thread_pool.init(gpa);4204 try thread_pool.init(.{ .allocator = gpa });
4205 defer thread_pool.deinit();4205 defer thread_pool.deinit();
42064206
4207 var cleanup_build_runner_dir: ?fs.Dir = null;4207 var cleanup_build_runner_dir: ?fs.Dir = null;