Skip to documentation
SLOP

tiny.profiling.host.dhat

Reference tiny.profiling host dhat

Defined in host.

API (8)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callshostdhat
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callstest; no linksrc.profiling.host.dhattest: profiling dhat classifies a mis...test; no linksrc.profiling.host.dhattest: profiling dhat rejects zero tot...test; no linksrc.profiling.host.dhattest: profiling dhat reports missing ...test; no linksrc.profiling.host.dhattest: profiling dhat summarizes a val...test; no linksrc.profiling.host.dhattest: profiling dhat wraps direct bin...+2 morehost.dhatplan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linksrc.profiling.host.dhattest: profiling dhat classifies a mis...test; no linksrc.profiling.host.dhattest: profiling dhat rejects zero tot...test; no linksrc.profiling.host.dhattest: profiling dhat reports missing ...test; no linksrc.profiling.host.dhattest: profiling dhat summarizes a val...hostsummarizeprivate; no linksrc.profiling.host.dhatcontradictsOwnedAllocationsprivate; no linksrc.profiling.host.dhatfailedprivate; no linksrc.profiling.host.dhatmissingToolprivate; no linksrc.profiling.host.dhatunobservedAllocatorTraffichost.dhatsummarize
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsNo direct callstest; no linksrc.profiling.host.dhattest: profiling dhat wraps direct bin...hostwraphost.dhatwrapArgv
Static calls · unresolved targets: 0 · external targets: 2.

Source: src/profiling/host/dhat.zig

zig
const std = @import("std");const capture = @import("capture");const sys = @import("sys");const root = @import("root.zig");pub const tool = "valgrind";pub const kind = "dhat";pub const mode = "heap";const allocator_traffic_unobserved = "allocator_traffic_unobserved";pub const Options = struct {};pub const Lane = struct {    capture_path: []const u8,    out_path: []const u8,    summary_path: []const u8,};pub fn plan(allocator: std.mem.Allocator, options: Options, workload_root: []const u8) !Lane {    _ = options;    return .{        .capture_path = try std.fs.path.join(allocator, &.{ workload_root, "dhat.capture.txt" }),        .out_path = try std.fs.path.join(allocator, &.{ workload_root, "dhat.out" }),        .summary_path = try std.fs.path.join(allocator, &.{ workload_root, "dhat.summary.json" }),    };}pub fn wrapArgv(allocator: std.mem.Allocator, options: Options, argv: []const []const u8, lane: Lane) ![]const []const u8 {    _ = options;    var wrapped: std.ArrayList([]const u8) = .empty;    try wrapped.appendSlice(allocator, &.{        tool,        "--tool=dhat",        try std.fmt.allocPrint(allocator, "--log-file={s}", .{lane.capture_path}),        try std.fmt.allocPrint(allocator, "--dhat-out-file={s}", .{lane.out_path}),    });    try wrapped.appendSlice(allocator, argv);    return try wrapped.toOwnedSlice(allocator);}pub fn summarize(    allocator: std.mem.Allocator,    lane: Lane,    exit_code: i64,    stderr_path: []const u8,    tool_available: bool,    max_benchmark_allocated_bytes: ?u64,) !root.Capture {    if (!tool_available) return missingTool(lane);    var summary = capture.dhat.summarizeCaptureFile(        allocator,        lane.capture_path,        lane.out_path,        mode,    ) catch |err| switch (err) {        error.FileNotFound => return try failed(            allocator,            lane,            exit_code,            stderr_path,            lane.capture_path,        ),        else => |actual| return actual,    };    if (contradictsOwnedAllocations(summary, max_benchmark_allocated_bytes)) {        summary.failure = allocator_traffic_unobserved;        try capture.dhat.writeSummaryFile(lane.summary_path, summary);        return unobservedAllocatorTraffic(lane);    }    if (!std.mem.eql(u8, summary.state(), "summary_parsed")) {        return try failed(allocator, lane, exit_code, stderr_path, lane.capture_path);    }    try capture.dhat.writeSummaryFile(lane.summary_path, summary);    return .{        .kind = kind,        .tool = tool,        .capture_path = lane.capture_path,        .summary_path = lane.summary_path,        .state = "summary_written",    };}fn contradictsOwnedAllocations(    summary: capture.dhat.Summary,    max_benchmark_allocated_bytes: ?u64,) bool {    const owned_bytes = max_benchmark_allocated_bytes orelse return false;    if (owned_bytes == 0 or summary.failure != null) return false;    if (!std.mem.eql(u8, summary.mode, mode)) return false;    return summary.total_allocated.bytes == 0;}fn unobservedAllocatorTraffic(lane: Lane) root.Capture {    return .{        .kind = kind,        .tool = tool,        .capture_path = lane.capture_path,        .summary_path = lane.summary_path,        .state = "evidence_invalid",        .caveat_kind = allocator_traffic_unobserved,        .caveat_message = "DHAT reported zero allocations while owned benchmark counters " ++            "reported allocator traffic",    };}fn missingTool(lane: Lane) root.Capture {    return .{        .kind = kind,        .tool = tool,        .capture_path = lane.capture_path,        .summary_path = lane.summary_path,        .state = "tool_missing",        .caveat_kind = "tool_unavailable",        .caveat_message = "valgrind is not runnable on this host; heap evidence was not captured",    };}fn failed(    allocator: std.mem.Allocator,    lane: Lane,    exit_code: i64,    stderr_path: []const u8,    capture_path: []const u8,) !root.Capture {    const row = try capture.caveat.classifyCommandCapture(allocator, .{        .phase = kind,        .exit_code = if (exit_code == 0) 1 else exit_code,        .timed_out = false,        .capture_path = capture_path,    }) orelse try capture.caveat.classifyCommandCapture(allocator, .{        .phase = kind,        .exit_code = 1,        .timed_out = false,        .capture_path = stderr_path,    }) orelse capture.caveat.classifyCommandText(.{        .phase = kind,        .exit_code = exit_code,        .timed_out = false,        .capture_path = capture_path,    }, "");    return .{        .kind = kind,        .tool = tool,        .capture_path = lane.capture_path,        .summary_path = lane.summary_path,        .state = "tool_failed",        .caveat_kind = row.kind,        .caveat_message = row.message,    };}test "profiling dhat wraps direct binaries in valgrind" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const allocator = arena_state.allocator();    const lane = try plan(allocator, .{}, "zig-out/profiling/run/workloads/w");    const argv = [_][]const u8{ "zig-out/bin/mprompt-bench", "--workers", "128" };    const wrapped = try wrapArgv(allocator, .{}, &argv, lane);    try std.testing.expectEqualStrings("valgrind", wrapped[0]);    try std.testing.expectEqualStrings("--tool=dhat", wrapped[1]);    try std.testing.expectEqualStrings("--log-file=zig-out/profiling/run/workloads/w/dhat.capture.txt", wrapped[2]);    try std.testing.expectEqualStrings("--dhat-out-file=zig-out/profiling/run/workloads/w/dhat.out", wrapped[3]);    try std.testing.expectEqualStrings("zig-out/bin/mprompt-bench", wrapped[4]);    try std.testing.expectEqualStrings("--workers", wrapped[wrapped.len - 2]);}test "profiling dhat summarizes a valgrind capture" {    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const allocator = arena_state.allocator();    const dir = try std.fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] });    const lane = try plan(allocator, .{}, dir);    try sys.fs.writeFile(lane.capture_path,        \\==100== DHAT, a dynamic heap analysis tool        \\==100== Total:     1,000 bytes in 10 blocks        \\==100== At t-gmax: 600 bytes in 4 blocks        \\==100== At t-end:  0 bytes in 0 blocks        \\==100== Reads:     2,000 bytes        \\==100== Writes:    1,500 bytes        \\    );    const stderr_path = try std.fs.path.join(allocator, &.{ dir, "stderr.txt" });    try sys.fs.writeFile(stderr_path, "");    const row = try summarize(allocator, lane, 0, stderr_path, true, 4_096);    try std.testing.expectEqualStrings("summary_written", row.state);    try std.testing.expect(row.caveat_kind == null);    try std.testing.expect(sys.fs.exists(lane.summary_path));}test "profiling dhat classifies a missing capture" {    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const allocator = arena_state.allocator();    const dir = try std.fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] });    const lane = try plan(allocator, .{}, dir);    const stderr_path = try std.fs.path.join(allocator, &.{ dir, "stderr.txt" });    try sys.fs.writeFile(stderr_path, "");    const row = try summarize(allocator, lane, 1, stderr_path, true, null);    try std.testing.expectEqualStrings("tool_failed", row.state);    try std.testing.expect(row.caveat_kind != null);}test "profiling dhat reports missing tools as caveats" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const allocator = arena_state.allocator();    const lane = try plan(allocator, .{}, "zig-out/profiling/run/workloads/w");    const row = try summarize(        allocator,        lane,        0,        "missing-stderr.txt",        false,        null,    );    try std.testing.expectEqualStrings("tool_missing", row.state);    try std.testing.expectEqualStrings("tool_unavailable", row.caveat_kind.?);}test "profiling dhat rejects zero totals contradicted by owned allocations" {    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const allocator = arena_state.allocator();    const dir = try std.fs.path.join(        allocator,        &.{ ".zig-cache", "tmp", tmp.sub_path[0..] },    );    const lane = try plan(allocator, .{}, dir);    try sys.fs.writeFile(        lane.capture_path,        "==100== Total:     0 bytes in 0 blocks\n",    );    const stderr_path = try std.fs.path.join(allocator, &.{ dir, "stderr.txt" });    try sys.fs.writeFile(stderr_path, "");    const uncorroborated = try summarize(        allocator,        lane,        0,        stderr_path,        true,        null,    );    try std.testing.expectEqualStrings("summary_written", uncorroborated.state);    const row = try summarize(allocator, lane, 0, stderr_path, true, 4_096);    try std.testing.expectEqualStrings("evidence_invalid", row.state);    try std.testing.expectEqualStrings(        allocator_traffic_unobserved,        row.caveat_kind.?,    );    const summary = try sys.fs.readFileAlloc(allocator, lane.summary_path, 8 * 1024);    try std.testing.expect(std.mem.indexOf(        u8,        summary,        "\"failure\": \"allocator_traffic_unobserved\"",    ) != null);}

Source: src/profiling/host/root.zig:5

zig
pub const dhat = runtime.dhat;

Complete caller list for host.dhat.plan

7 direct callers.

Audit

Definitions9
Public names9
Members3
Version26.7.0
Revisiondaab053ee433