From 2996eb558756c697e2ccfe9691356e536c88916b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 3 Mar 2023 16:39:08 -0700 Subject: [PATCH] std.Build.RunStep: add maxrss, duration, and cached status --- lib/std/Build/ObjCopyStep.zig | 2 +- lib/std/Build/Step.zig | 10 ++++++++- lib/std/zig/Server.zig | 13 ++++++++++- src/Compilation.zig | 3 +++ src/main.zig | 41 ++++++++++++++++++++++++++++------- 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/lib/std/Build/ObjCopyStep.zig b/lib/std/Build/ObjCopyStep.zig index 13046b3efe..5f675ed383 100644 --- a/lib/std/Build/ObjCopyStep.zig +++ b/lib/std/Build/ObjCopyStep.zig @@ -113,7 +113,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }; try argv.appendSlice(&.{ full_src_path, full_dest_path }); - _ = try step.spawnZigProcess(argv.items, prog_node); + _ = try step.evalZigProcess(argv.items, prog_node); self.output_file.path = full_dest_path; try man.writeManifest(); diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index be14373afe..37bd66678b 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -234,10 +234,12 @@ pub fn evalZigProcess( child.stdin_behavior = .Pipe; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; + child.request_resource_usage_statistics = true; child.spawn() catch |err| return s.fail("unable to spawn {s}: {s}", .{ argv[0], @errorName(err), }); + var timer = try std.time.Timer.start(); var poller = std.io.poll(gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, @@ -301,7 +303,10 @@ pub fn evalZigProcess( sub_prog_node.?.activate(); }, .emit_bin_path => { - result = try arena.dupe(u8, body); + const EbpHdr = std.zig.Server.Message.EmitBinPath; + const ebp_hdr = @ptrCast(*align(1) const EbpHdr, body); + s.result_cached = ebp_hdr.flags.cache_hit; + result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]); }, _ => { // Unrecognized message. @@ -323,6 +328,9 @@ pub fn evalZigProcess( const term = child.wait() catch |err| { return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(err) }); }; + s.result_duration_ns = timer.read(); + s.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0; + try handleChildProcessTerm(s, term, null, argv); if (s.result_error_bundle.errorMessageCount() > 0) { diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index 76f2303f6b..d34b2193e9 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -12,7 +12,7 @@ pub const Message = struct { error_bundle, /// Body is a UTF-8 string. progress, - /// Body is a UTF-8 string. + /// Body is a EmitBinPath. emit_bin_path, _, }; @@ -25,4 +25,15 @@ pub const Message = struct { extra_len: u32, string_bytes_len: u32, }; + + /// Trailing: + /// * the file system path the emitted binary can be found + pub const EmitBinPath = extern struct { + flags: Flags, + + pub const Flags = packed struct(u8) { + cache_hit: bool, + reserved: u7 = 0, + }; + }; }; diff --git a/src/Compilation.zig b/src/Compilation.zig index 28e7c43702..b542c86511 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -100,6 +100,7 @@ job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, alloc_failure_occurred: bool = false, formatted_panics: bool = false, +last_update_was_cache_hit: bool = false, c_source_files: []const CSourceFile, clang_argv: []const []const u8, @@ -1860,6 +1861,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void defer tracy_trace.end(); comp.clearMiscFailures(); + comp.last_update_was_cache_hit = false; var man: Cache.Manifest = undefined; defer if (comp.whole_cache_manifest != null) man.deinit(); @@ -1887,6 +1889,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void return err; }; if (is_hit) { + comp.last_update_was_cache_hit = true; log.debug("CacheMode.whole cache hit for {s}", .{comp.bin_file.options.root_name}); const digest = man.final(); diff --git a/src/main.zig b/src/main.zig index f81911ffd0..699122d26f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3578,9 +3578,11 @@ fn serve( var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = arena_instance.allocator(); - var output_path: []const u8 = undefined; - try cmdTranslateC(comp, arena, &output_path); - try serveStringMessage(out, .emit_bin_path, output_path); + var output: TranslateCOutput = undefined; + try cmdTranslateC(comp, arena, &output); + try serveEmitBinPath(out, output.path, .{ + .flags = .{ .cache_hit = output.cache_hit }, + }); continue; } @@ -3760,10 +3762,26 @@ fn serveUpdateResults(out: fs.File, comp: *Compilation) !void { } else if (comp.bin_file.options.emit) |emit| { const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); defer gpa.free(full_path); - try serveStringMessage(out, .emit_bin_path, full_path); + try serveEmitBinPath(out, full_path, .{ + .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, + }); } } +fn serveEmitBinPath( + out: fs.File, + fs_path: []const u8, + header: std.zig.Server.Message.EmitBinPath, +) !void { + try serveMessage(out, .{ + .tag = .emit_bin_path, + .bytes_len = @intCast(u32, fs_path.len + @sizeOf(std.zig.Server.Message.EmitBinPath)), + }, &.{ + std.mem.asBytes(&header), + fs_path, + }); +} + fn serveStringMessage(out: fs.File, tag: std.zig.Server.Message.Tag, s: []const u8) !void { try serveMessage(out, .{ .tag = tag, @@ -4115,7 +4133,12 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void } } -fn cmdTranslateC(comp: *Compilation, arena: Allocator, output_path: ?*[]const u8) !void { +const TranslateCOutput = struct { + path: []const u8, + cache_hit: bool, +}; + +fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*TranslateCOutput) !void { if (!build_options.have_llvm) fatal("cannot translate-c: compiler built without LLVM extensions", .{}); @@ -4126,14 +4149,16 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, output_path: ?*[]const u8 var man: Cache.Manifest = comp.obtainCObjectCacheManifest(); man.want_shared_lock = false; - defer if (output_path != null) man.deinit(); + defer man.deinit(); man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| { fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) }); }; + if (fancy_output) |p| p.cache_hit = true; const digest = if (try man.hit()) man.final() else digest: { + if (fancy_output) |p| p.cache_hit = false; var argv = std.ArrayList([]const u8).init(arena); try argv.append(""); // argv[0] is program name, actual args start at [1] @@ -4229,11 +4254,11 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, output_path: ?*[]const u8 break :digest digest; }; - if (output_path) |out_path| { + if (fancy_output) |p| { const full_zig_path = try comp.local_cache_directory.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename, }); - out_path.* = full_zig_path; + p.path = full_zig_path; } else { const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename }); const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| {