tiny.profiling.driver.artifact
Defined in driver.
API (8)
Actions
Public operations.
benchmarkReductionDomaincollectCapturescollectMeasuredArtifactshasControlResultperturbationStructuredPathsreduceMeasuredBenchmarksretainedArtifactPathsvalidateRetainedTracyArtifacts
Source
Source: src/profiling/driver/artifact.zig
zig
const std = @import("std");const sys = @import("sys");const allocation_trace = @import("../capture/root.zig").memtrace;const catalog = @import("../root.zig").catalog;const coz = @import("../capture/root.zig").coz;const execute = @import("../root.zig").execute;const host = @import("../root.zig").host;const ingest = @import("../root.zig").ingest;const perturbation = @import("../root.zig").perturbation;const record = @import("../root.zig").record;const reducer = @import("../root.zig").reduction;const trace_capture = @import("../capture/root.zig").tracy;const CompletedWorkload = @import("root.zig").model.CompletedWorkload;const PreparedWorkload = @import("root.zig").model.PreparedWorkload;const Request = @import("root.zig").model.Request;const WorkloadContext = @import("root.zig").model.WorkloadContext;const rebaseCaptures = @import("root.zig").paths.rebaseCaptures;const recordAllocationRepetition = @import("root.zig").acquire.recordAllocationRepetition;pub fn collectCaptures( allocator: std.mem.Allocator, context: *const WorkloadContext, workload: catalog.Workload, prepared: PreparedWorkload, completed: CompletedWorkload, scope_label: []const u8, max_benchmark_allocated_bytes: ?u64,) ![]const host.Capture { std.debug.assert(scope_label.len > 0); std.debug.assert(prepared.paths.root.len > 0); if (prepared.execution_plan.missing_bin and context.request.host_lanes.any()) { return try host.missingBinary( allocator, context.request.host_lanes, prepared.paths.root, context.tool_probe, ); } if (completed.setup_failed) { return try host.setupFailed( allocator, context.request.host_lanes, prepared.paths.root, context.tool_probe, ); } if (completed.prepare_failed) return &.{}; if (completed.reset_failed) return &.{}; if (completed.warmup_failed) { return try host.warmupFailed( allocator, context.request.host_lanes, prepared.paths.root, context.tool_probe, ); } const artifacts = retainedArtifactPaths(prepared.paths, completed.executions); const host_captures = try host.summarize( allocator, context.process_io, prepared.wrapped, completed.execution.exit_code, artifacts.stderr, context.tool_probe, scope_label, workload.name, max_benchmark_allocated_bytes, ); const trace_captures = try trace_capture.appendCapture(allocator, host_captures, .{ .enabled = context.request.tracy, .exit_code = completed.execution.exit_code, .capture_path = artifacts.tracy_jsonl, .summary_path = artifacts.tracy_summary, }); const allocation_captures = try allocation_trace.appendCapture(allocator, trace_captures, .{ .enabled = context.request.trace_allocations or workload.tracesAllocationsByDefault(), .exit_code = completed.execution.exit_code, .capture_path = artifacts.allocations, .summary_path = prepared.paths.allocations_summary, }); const captures = try coz.appendCapture(allocator, allocation_captures, .{ .enabled = context.request.control.causal, .exit_code = completed.execution.exit_code, .capture_path = artifacts.coz_jsonl, .summary_path = artifacts.coz_analysis, }); return try rebaseCaptures( allocator, captures, prepared.absolute_root, prepared.paths.root, );}pub fn retainedArtifactPaths( paths: record.WorkloadPaths, executions: []const record.MeasuredExecution,) record.ExecutionPaths { var index = executions.len; while (index > 0) { index -= 1; if (executions[index].paths) |actual| return actual; } return .{ .root = paths.root, .stdout = paths.stdout, .stderr = paths.stderr, .bench_jsonl = paths.bench_jsonl, .coz_jsonl = paths.coz_jsonl, .coz_analysis = paths.coz_analysis, .tracy_jsonl = paths.tracy_jsonl, .tracy_summary = paths.tracy_summary, .allocations = paths.allocations, .structured = paths.structured, };}fn structuredPaths(paths: record.WorkloadPaths) ingest.Paths { std.debug.assert(paths.root.len > 0); std.debug.assert(paths.structured.len > paths.root.len); return .{ .stdout = paths.stdout, .stderr = paths.stderr, .bench_jsonl = paths.bench_jsonl, .coz_jsonl = paths.coz_jsonl, .coz_analysis = paths.coz_analysis, .tracy_summary = paths.tracy_summary, .allocations = paths.allocations, .structured = paths.structured, };}fn executionStructuredPaths(paths: record.ExecutionPaths) ingest.Paths { std.debug.assert(paths.root.len > 0); std.debug.assert(paths.structured.len > paths.root.len); return .{ .stdout = paths.stdout, .stderr = paths.stderr, .bench_jsonl = paths.bench_jsonl, .coz_jsonl = paths.coz_jsonl, .coz_analysis = paths.coz_analysis, .tracy_summary = paths.tracy_summary, .allocations = paths.allocations, .structured = paths.structured, };}pub fn perturbationStructuredPaths(paths: perturbation.Paths) ingest.Paths { return .{ .stdout = paths.stdout, .stderr = paths.stderr, .bench_jsonl = paths.bench_jsonl, .coz_jsonl = paths.coz_jsonl, .coz_analysis = paths.coz_analysis, .tracy_summary = paths.tracy_summary, .allocations = paths.allocations, .structured = paths.structured, };}pub fn hasControlResult(pairs: []const perturbation.Pair) bool { for (pairs) |pair| { if (pair.control != null) return true; } return false;}pub fn collectMeasuredArtifacts( allocator: std.mem.Allocator, context: *const WorkloadContext, workload: catalog.Workload, prepared: PreparedWorkload, executions: []record.MeasuredExecution,) !ingest.Summary { if (executions.len == 0 or executions[0].paths == null) { return try ingest.collect( allocator, workload, structuredPaths(prepared.paths), ); } const planned_execution_count = plannedMeasuredExecutionCount( context, prepared, ); var result = ingest.Summary{ .rows = 0, .parse_errors = 0, .sources = 0 }; for (executions) |*execution| { const execution_paths = execution.paths orelse return error.InvalidExecutionArtifacts; const summary = try ingest.collect( allocator, workload, executionStructuredPaths(execution_paths), ); execution.structured_rows = summary.rows; execution.structured_parse_errors = summary.parse_errors; try recordAllocationRepetition( allocator, context, workload, prepared, execution_paths.allocations, execution.result, execution.index, planned_execution_count, ); result.rows = try std.math.add(usize, result.rows, summary.rows); result.parse_errors = try std.math.add( usize, result.parse_errors, summary.parse_errors, ); result.sources = try std.math.add(usize, result.sources, summary.sources); result.max_benchmark_allocated_bytes = maxOptionalU64( result.max_benchmark_allocated_bytes, summary.max_benchmark_allocated_bytes, ); } return result;}fn plannedMeasuredExecutionCount( context: *const WorkloadContext, prepared: PreparedWorkload,) usize { if (!context.tool_probe.available or context.request.host_lanes.counters == null) { return context.request.measure_repeat; } const lane = prepared.wrapped.lane orelse return context.request.measure_repeat; return switch (lane) { .counters => |counter| counter.runs.len, else => context.request.measure_repeat, };}fn maxOptionalU64(left: ?u64, right: ?u64) ?u64 { if (left == null) return right; if (right == null) return left; return @max(left.?, right.?);}pub fn reduceMeasuredBenchmarks( allocator: std.mem.Allocator, domain: reducer.DomainDeclaration, executions: []const record.MeasuredExecution,) !reducer.Result { if (executions.len > reducer.max_processes) return error.TooManyProcesses; if (!reducer.directBenchmarkDomain(domain)) { return .{ .not_applicable = .{ .reason = .outside_direct_benchmark_domain, .process_count = executions.len, } }; } var inputs: [reducer.max_processes]reducer.Execution = undefined; for (executions, inputs[0..executions.len]) |execution, *input| { const paths = execution.paths; input.* = .{ .index = execution.index, .acquisition_position = execution.acquisition_position, .exit_code = execution.result.exit_code, .bench_jsonl = if (paths) |actual| actual.bench_jsonl else "", .structured = if (paths) |actual| actual.structured else "", }; } return try reducer.capture(allocator, inputs[0..executions.len]);}pub fn benchmarkReductionDomain( request: Request, surface: catalog.Surface, default_allocation_trace: bool, execution_plan: execute.Plan,) reducer.DomainDeclaration { return .{ .benchmark_surface = surface == .benchmark, .direct_execution = execution_plan.direct, .host_profiler = request.host_lanes.any(), .tracy = request.tracy, .causal = request.control.causal, .allocation_trace = request.trace_allocations or default_allocation_trace, .capture_control = request.capture_control.enabled(), };}fn validateTracyArtifacts(paths: anytype) !void { const trace = sys.fs.statFile(paths.tracy_jsonl) catch return error.TracyTraceMissing; if (trace.size == 0) return error.TracyTraceEmpty; const summary = sys.fs.statFile(paths.tracy_summary) catch return error.TracySummaryMissing; if (summary.size == 0) return error.TracySummaryEmpty;}pub fn validateRetainedTracyArtifacts( workload_paths: record.WorkloadPaths, executions: []const record.MeasuredExecution,) !void { var uses_execution_paths = false; var first_failure: ?anyerror = null; for (executions) |execution| { const paths = execution.paths orelse continue; uses_execution_paths = true; validateTracyArtifacts(paths) catch |err| { try appendTracyFailure(paths.stderr, err); if (first_failure == null) first_failure = err; }; } if (!uses_execution_paths) { validateTracyArtifacts(workload_paths) catch |err| { try appendTracyFailure(workload_paths.stderr, err); return err; }; } if (first_failure) |err| return err;}fn appendTracyFailure(path: []const u8, err: anyerror) !void { var buffer: [128]u8 = undefined; const message = try std.fmt.bufPrint( &buffer, "profile: Tracy capture incomplete: {s}\n", .{@errorName(err)}, ); try sys.fs.appendFile(path, &.{message});}test "profiling driver requires complete Tracy artifacts" { 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 root = try tmp.parent_dir.realPathFileAlloc( std.Options.debug_io, tmp.sub_path[0..], allocator, ); const run_paths = record.Paths{ .root = root, .manifest = root, .results = root, .workloads = root, }; const paths = try record.makeWorkloadPaths(allocator, run_paths, "trace"); try std.testing.expectError(error.TracyTraceMissing, validateTracyArtifacts(paths)); try sys.fs.writeFile(paths.tracy_jsonl, ""); try sys.fs.writeFile(paths.tracy_summary, ""); try std.testing.expectError(error.TracyTraceEmpty, validateTracyArtifacts(paths)); try sys.fs.writeFile(paths.tracy_jsonl, "{}\n"); try std.testing.expectError(error.TracySummaryEmpty, validateTracyArtifacts(paths)); try sys.fs.writeFile(paths.tracy_summary, "{}\n"); try validateTracyArtifacts(paths);}test "profiling driver validates each retained Tracy execution" { 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 root = try tmp.parent_dir.realPathFileAlloc( std.Options.debug_io, tmp.sub_path[0..], allocator, ); const run_paths = record.Paths{ .root = root, .manifest = root, .results = root, .workloads = root, }; const workload_paths = try record.makeWorkloadPaths(allocator, run_paths, "trace"); const first = try record.executionPaths(allocator, workload_paths, 2, 1); const second = try record.executionPaths(allocator, workload_paths, 2, 2); for ([_]record.ExecutionPaths{ first, second }) |paths| { try sys.fs.createDirPath(paths.root); try sys.fs.writeFile(paths.stderr, ""); try sys.fs.writeFile(paths.tracy_jsonl, "{}\n"); try sys.fs.writeFile(paths.tracy_summary, "{}\n"); } const executions = [_]record.MeasuredExecution{ .{ .index = 1, .result = .{ .pid = 101, .exit_code = 0, .wall_ns = 1 }, .paths = first }, .{ .index = 2, .result = .{ .pid = 102, .exit_code = 0, .wall_ns = 1 }, .paths = second }, }; try validateRetainedTracyArtifacts(workload_paths, &executions); try sys.fs.writeFile(second.tracy_summary, ""); try std.testing.expectError( error.TracySummaryEmpty, validateRetainedTracyArtifacts(workload_paths, &executions), ); const stderr = try sys.fs.readFileAlloc(allocator, second.stderr, 4096); try std.testing.expect(std.mem.indexOf(u8, stderr, "TracySummaryEmpty") != null);}test "profiling driver keeps repeated non benchmarks outside reducer domain" { const request = Request{ .selection = .{}, .run_id = "test", .execution_scope = .binary, .measure_repeat = 2, }; const direct = execute.Plan{ .argv = &.{"benchmark"}, .direct = true, }; try std.testing.expect(reducer.directBenchmarkDomain(benchmarkReductionDomain( request, .benchmark, false, direct, ))); try std.testing.expect(!reducer.directBenchmarkDomain(benchmarkReductionDomain( request, .profile, false, direct, ))); try std.testing.expect(!reducer.directBenchmarkDomain(benchmarkReductionDomain( request, .benchmark, true, direct, )));}Source: src/profiling/driver/root.zig:2
zig
pub const artifact = @import("artifact.zig");Audit
| Definitions | 9 |
|---|---|
| Public names | 9 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |