Commit 2996eb5587

Andrew Kelley <andrew@ziglang.org>
2023-03-04 00:39:08
std.Build.RunStep: add maxrss, duration, and cached status
1 parent 80d1976
Changed files (5)
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();
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) {
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,
+        };
+    };
 };
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();
 
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| {