tiny.profiling.measurement
Defined in tiny.profiling.
API (22)
Actions
Public operations.
Distribution.namecomparisonSupportloadPerfStatSummaryoutputRetentionparseExecutionsparseWarmupspointWallDistributionsummarizetotalWallNsvalidateProfilerArtifactswallEffectSamples
Types and contracts
Public types and contracts.
ComparisonInputComparisonSupportDistributionExecutionExecutionArtifactsOutputRetentionResourceTotalsStatsWallDistribution
Values and defaults
Public values and defaults.
Source
Source: src/profiling/measurement.zig
zig
const std = @import("std");const capture = @import("capture");const sys = @import("sys");const host = @import("host/root.zig");const json = @import("json.zig");const order = @import("order.zig");const perturbation = @import("perturbation.zig");pub const wall_statistic = "mean_per_execution";pub const wall_effect_method = "deterministic_percentile_bootstrap_unpaired_mean_percent_change";pub const ExecutionArtifacts = struct { root: []const u8, stdout: []const u8, stderr: []const u8, bench_jsonl: []const u8, coz_jsonl: []const u8, coz_analysis: []const u8, tracy_jsonl: []const u8, tracy_summary: []const u8, allocations: []const u8, structured: []const u8, structured_rows: usize, structured_parse_errors: usize,};pub const Execution = struct { index: usize = 0, acquisition_position: ?usize = null, pid: ?u64 = null, exit_code: i64, wall_ns: u64, resource_usage_source: ?sys.process.ResourceUsageSource = null, maxrss_kib: ?i64 = null, user_s: ?f64 = null, system_s: ?f64 = null, minor_page_faults: ?u64 = null, major_page_faults: ?u64 = null, voluntary_context_switches: ?u64 = null, involuntary_context_switches: ?u64 = null, artifacts: ?ExecutionArtifacts = null,};pub const OutputRetention = enum { all_measured_executions, profiler_capture_contract, no_measured_execution,};const SpawnState = enum { spawned, spawn_failed,};const ArtifactLayout = enum { workload_root, numbered_execution_directories, none,};const AllocationRetention = enum { disabled, all_measured_executions, single_measured_execution, profiler_capture_contract, no_measured_execution,};pub const Distribution = enum { raw_executions, grouped_repetition_means, legacy_summary, point_estimate, pub fn name(self: Distribution) []const u8 { return @tagName(self); }};pub const WallDistribution = struct { kind: Distribution, sample_count: usize, mean_ns: f64, min_ns: ?f64 = null, median_ns: ?f64 = null, p95_ns: ?f64 = null, p99_ns: ?f64 = null, max_ns: ?f64 = null, stddev_ns: ?f64 = null, coefficient_of_variation_percent: ?f64 = null,};pub const ResourceTotals = struct { source: ?sys.process.ResourceUsageSource = null, user_s: ?f64 = null, system_s: ?f64 = null, minor_page_faults: ?f64 = null, major_page_faults: ?f64 = null, voluntary_context_switches: ?f64 = null, involuntary_context_switches: ?f64 = null,};const ResourceCountField = enum { minor_page_faults, major_page_faults, voluntary_context_switches, involuntary_context_switches,};pub const Stats = struct { wall_ns: u64, total_wall_ns: u64, execution_count: usize, executions: []const Execution, wall_distribution: WallDistribution, resource_usage_source: ?sys.process.ResourceUsageSource, user_s: ?f64, system_s: ?f64, minor_page_faults: ?f64, major_page_faults: ?f64, voluntary_context_switches: ?f64, involuntary_context_switches: ?f64,};pub const ComparisonSupport = enum { supported, scope_mismatch, measurement_order_mismatch, warmup_design_mismatch, capture_mismatch, capture_perturbation_mismatch, perf_stat_summary_missing, perf_stat_events_mismatch, perf_stat_groups_mismatch, perf_stat_design_mismatch,};pub const ComparisonInput = struct { scope: []const u8, acquisition: order.Context = .{ .blocked = .{} }, warmup_count: usize = 0, captures: []const host.Capture, perf_stat: ?capture.perfstat.Summary, capture_perturbation: ?perturbation.Configuration = null,};pub fn parseExecutions( allocator: std.mem.Allocator, object: std.json.ObjectMap, workload_root: []const u8,) ![]const Execution { const value = object.get("measurement") orelse return error.InvalidProfilingJson; const group = try json.object(value); const retention = try outputRetention(group); const layout = try artifactLayout(group); const executions = try parseExecutionGroup( allocator, group, retention == .all_measured_executions, true, ); try validateOutputRetention(executions, retention, layout, workload_root); try validateAllocationRetention(group, retention, executions.len); return executions;}pub fn parseWarmups( allocator: std.mem.Allocator, object: std.json.ObjectMap,) ![]const Execution { const value = object.get("warmup") orelse return &.{}; return try parseExecutionGroup( allocator, try json.object(value), false, false, );}fn parseExecutionGroup( allocator: std.mem.Allocator, group_object: std.json.ObjectMap, require_artifacts: bool, require_pid: bool,) ![]const Execution { const executions_value = group_object.get("executions") orelse return error.InvalidProfilingJson; const rows = try json.array(executions_value); if (rows.items.len > host.process.max_executions) return error.InvalidProfilingJson; const expected_count = json.asU64(group_object.get("execution_count")) orelse return error.InvalidProfilingJson; if (expected_count != rows.items.len) return error.InvalidProfilingJson; const result = try allocator.alloc(Execution, rows.items.len); for (rows.items, 0..) |item, index| { const row = try json.object(item); const recorded_index = json.asU64(row.get("index")) orelse return error.InvalidProfilingJson; if (recorded_index != index + 1) return error.InvalidProfilingJson; const pid = if (require_pid) try parsePid(row) else try parseOptionalPid(row); const exit_code = json.asI64(row.get("exit_code")) orelse return error.InvalidProfilingJson; if (require_pid) try validateSpawnState(row, pid, exit_code); result[index] = .{ .index = index + 1, .acquisition_position = try parseAcquisitionPosition(row), .pid = pid, .exit_code = exit_code, .wall_ns = json.asU64(row.get("wall_ns")) orelse return error.InvalidProfilingJson, .resource_usage_source = try parseResourceUsageSource(row), .maxrss_kib = json.asI64(row.get("max_rss_kib")), .user_s = json.asF64(row.get("user_s")), .system_s = json.asF64(row.get("system_s")), .minor_page_faults = json.asU64(row.get("minor_page_faults")), .major_page_faults = json.asU64(row.get("major_page_faults")), .voluntary_context_switches = json.asU64(row.get("voluntary_context_switches")), .involuntary_context_switches = json.asU64(row.get("involuntary_context_switches")), .artifacts = try parseExecutionArtifacts(row, require_artifacts), }; } return result;}fn validateSpawnState( row: std.json.ObjectMap, pid: ?u64, exit_code: i64,) !void { const name = json.string(row.get("spawn_state")) orelse return error.InvalidProfilingJson; const state = std.meta.stringToEnum(SpawnState, name) orelse return error.InvalidProfilingJson; const valid = switch (state) { .spawned => (pid orelse 0) > 0, .spawn_failed => pid == null and (exit_code == 126 or exit_code == 127), }; if (!valid) return error.InvalidProfilingJson;}fn parsePid(row: std.json.ObjectMap) !?u64 { const value = row.get("pid") orelse return error.InvalidProfilingJson; return try parsePidValue(value);}fn parseOptionalPid(row: std.json.ObjectMap) !?u64 { const value = row.get("pid") orelse return null; return try parsePidValue(value);}fn parsePidValue(value: std.json.Value) !?u64 { return switch (value) { .null => null, .integer => |integer| std.math.cast(u64, integer) orelse error.InvalidProfilingJson, else => error.InvalidProfilingJson, };}pub fn outputRetention(group: std.json.ObjectMap) !OutputRetention { const name = json.string(group.get("workload_output_retention")) orelse return error.InvalidProfilingJson; return std.meta.stringToEnum(OutputRetention, name) orelse error.InvalidProfilingJson;}fn artifactLayout(group: std.json.ObjectMap) !ArtifactLayout { const name = json.string(group.get("measured_artifact_layout")) orelse return error.InvalidProfilingJson; return std.meta.stringToEnum(ArtifactLayout, name) orelse error.InvalidProfilingJson;}fn validateAllocationRetention( group: std.json.ObjectMap, output_retention: OutputRetention, execution_count: usize,) !void { const name = json.string(group.get("allocation_summary_retention")) orelse return error.InvalidProfilingJson; const retention = std.meta.stringToEnum(AllocationRetention, name) orelse return error.InvalidProfilingJson; if (retention == .disabled) return; const valid = switch (retention) { .disabled => unreachable, .all_measured_executions => output_retention == .all_measured_executions and execution_count > 1, .single_measured_execution => output_retention == .all_measured_executions and execution_count == 1, .profiler_capture_contract => output_retention == .profiler_capture_contract, .no_measured_execution => output_retention == .no_measured_execution, }; if (!valid) return error.InvalidProfilingJson;}pub fn validateProfilerArtifacts( artifacts: ExecutionArtifacts, workload_root: []const u8,) !void { try validateArtifactRoot(artifacts, workload_root, .workload_root, 1);}fn validateOutputRetention( executions: []const Execution, retention: OutputRetention, layout: ArtifactLayout, workload_root: []const u8,) !void { switch (retention) { .all_measured_executions => { if (executions.len == 0 or layout == .none) { return error.InvalidProfilingJson; } try validateExecutionArtifacts(executions, workload_root, layout); }, .profiler_capture_contract => { if (executions.len == 0 or layout != .none) { return error.InvalidProfilingJson; } for (executions) |execution| { if (execution.artifacts != null) return error.InvalidProfilingJson; } }, .no_measured_execution => { if (executions.len != 0 or layout != .none) { return error.InvalidProfilingJson; } }, }}fn parseAcquisitionPosition(row: std.json.ObjectMap) !?usize { const item = row.get("acquisition_position") orelse return null; const value = switch (item) { .integer => |integer| std.math.cast(u64, integer) orelse return error.InvalidProfilingJson, else => return error.InvalidProfilingJson, }; const position = std.math.cast(usize, value) orelse return error.InvalidProfilingJson; if (position == 0) return error.InvalidProfilingJson; return position;}fn parseExecutionArtifacts( row: std.json.ObjectMap, required: bool,) !?ExecutionArtifacts { const value = row.get("artifacts") orelse { if (required) return error.InvalidProfilingJson; return null; }; if (value == .null) { if (required) return error.InvalidProfilingJson; return null; } const object = try json.object(value); return .{ .root = try requiredPath(object, "root"), .stdout = try requiredPath(object, "stdout"), .stderr = try requiredPath(object, "stderr"), .bench_jsonl = try requiredPath(object, "bench_jsonl"), .coz_jsonl = try requiredPath(object, "coz_jsonl"), .coz_analysis = try requiredPath(object, "coz_analysis"), .tracy_jsonl = try requiredPath(object, "tracy_jsonl"), .tracy_summary = try requiredPath(object, "tracy_summary"), .allocations = try requiredPath(object, "allocations"), .structured = try requiredPath(object, "structured"), .structured_rows = try requiredCount(object, "structured_rows"), .structured_parse_errors = try requiredCount( object, "structured_parse_errors", ), };}fn requiredPath(object: std.json.ObjectMap, field: []const u8) ![]const u8 { const path = json.string(object.get(field)) orelse return error.InvalidProfilingJson; if (path.len == 0) return error.InvalidProfilingJson; return path;}fn requiredCount(object: std.json.ObjectMap, field: []const u8) !usize { return std.math.cast( usize, json.asU64(object.get(field)) orelse return error.InvalidProfilingJson, ) orelse error.InvalidProfilingJson;}fn validateExecutionArtifacts( executions: []const Execution, workload_root: []const u8, layout: ArtifactLayout,) !void { for (executions, 0..) |execution, index| { const artifacts = execution.artifacts orelse return error.InvalidProfilingJson; try validateArtifactRoot( artifacts, workload_root, layout, index + 1, ); for (executions[0..index]) |previous| { if (std.mem.eql(u8, previous.artifacts.?.root, artifacts.root)) { return error.InvalidProfilingJson; } } }}fn validateArtifactRoot( artifacts: ExecutionArtifacts, workload_root: []const u8, layout: ArtifactLayout, execution_index: usize,) !void { switch (layout) { .workload_root => if (!std.mem.eql(u8, artifacts.root, workload_root)) { return error.InvalidProfilingJson; }, .numbered_execution_directories => try validateRepeatedArtifactRoot( artifacts.root, workload_root, execution_index, ), .none => return error.InvalidProfilingJson, } inline for (.{ .{ artifacts.stdout, "stdout.txt" }, .{ artifacts.stderr, "stderr.txt" }, .{ artifacts.bench_jsonl, "bench.jsonl" }, .{ artifacts.coz_jsonl, "bench.coz.jsonl" }, .{ artifacts.coz_analysis, "bench.coz.analysis.json" }, .{ artifacts.tracy_jsonl, "bench.tracy.jsonl" }, .{ artifacts.tracy_summary, "bench.tracy.summary.jsonl" }, .{ artifacts.allocations, "allocations.jsonl" }, .{ artifacts.structured, "structured.jsonl" }, }) |path| { if (!exactArtifactPath(path[0], artifacts.root, path[1])) { return error.InvalidProfilingJson; } }}fn validateRepeatedArtifactRoot( root: []const u8, workload_root: []const u8, execution_index: usize,) !void { var suffix_buffer: [3]u8 = undefined; const suffix = std.fmt.bufPrint(&suffix_buffer, "{d:0>3}", .{execution_index}) catch return error.InvalidProfilingJson; if (!std.mem.eql(u8, std.fs.path.basename(root), suffix)) { return error.InvalidProfilingJson; } const executions_root = std.fs.path.dirname(root) orelse return error.InvalidProfilingJson; if (!std.mem.eql(u8, std.fs.path.basename(executions_root), "executions")) { return error.InvalidProfilingJson; } const parent = std.fs.path.dirname(executions_root) orelse return error.InvalidProfilingJson; if (!std.mem.eql(u8, parent, workload_root)) return error.InvalidProfilingJson;}fn exactArtifactPath(path: []const u8, root: []const u8, basename: []const u8) bool { const parent = std.fs.path.dirname(path) orelse return false; return std.mem.eql(u8, parent, root) and std.mem.eql(u8, std.fs.path.basename(path), basename);}fn parseResourceUsageSource( row: std.json.ObjectMap,) !?sys.process.ResourceUsageSource { const text = json.string(row.get("resource_usage_source")) orelse return null; return std.meta.stringToEnum(sys.process.ResourceUsageSource, text) orelse error.InvalidProfilingJson;}pub fn summarize( total_wall_ns: u64, resources: ResourceTotals, executions: []const Execution, perf_stat: ?capture.perfstat.Summary,) !Stats { const execution_count = if (executions.len != 0) executions.len else if (perf_stat) |summary| std.math.cast( usize, capture.perfstat.measurementDesign(summary).execution_count, ) orelse 1 else 1; const actual_count = @max(execution_count, 1); if (executions.len != 0) { if (totalWallNs(executions) != total_wall_ns) { return error.InvalidProfilingJson; } const wall_distribution = try rawWallDistribution(executions, perf_stat); return .{ .wall_ns = meanExecutionWallNs(executions), .total_wall_ns = total_wall_ns, .execution_count = actual_count, .executions = executions, .wall_distribution = wall_distribution, .resource_usage_source = try commonResourceUsageSource(executions), .user_s = meanExecutionOptionalF64(executions, .user_s), .system_s = meanExecutionOptionalF64(executions, .system_s), .minor_page_faults = meanExecutionOptionalU64(executions, .minor_page_faults), .major_page_faults = meanExecutionOptionalU64(executions, .major_page_faults), .voluntary_context_switches = meanExecutionOptionalU64( executions, .voluntary_context_switches, ), .involuntary_context_switches = meanExecutionOptionalU64( executions, .involuntary_context_switches, ), }; } try validateResourceTotals(resources); const divisor = @as(f64, @floatFromInt(actual_count)); const mean_ns = @as(f64, @floatFromInt(total_wall_ns)) / divisor; return .{ .wall_ns = total_wall_ns / actual_count, .total_wall_ns = total_wall_ns, .execution_count = actual_count, .executions = executions, .wall_distribution = summaryWallDistribution( mean_ns, actual_count, perf_stat, ), .resource_usage_source = resources.source, .user_s = divideOptionalF64(resources.user_s, divisor), .system_s = divideOptionalF64(resources.system_s, divisor), .minor_page_faults = divideOptionalF64(resources.minor_page_faults, divisor), .major_page_faults = divideOptionalF64(resources.major_page_faults, divisor), .voluntary_context_switches = divideOptionalF64( resources.voluntary_context_switches, divisor, ), .involuntary_context_switches = divideOptionalF64( resources.involuntary_context_switches, divisor, ), };}pub fn pointWallDistribution(wall_ns: u64) WallDistribution { return .{ .kind = .point_estimate, .sample_count = 1, .mean_ns = @floatFromInt(wall_ns), };}pub fn wallEffectSamples( scratch: []f64, executions: []const Execution, perf_stat: ?capture.perfstat.Summary,) ![]f64 { if (executions.len == 0) return scratch[0..0]; if (executions.len > host.process.max_executions or scratch.len < executions.len) { return error.InvalidProfilingJson; } const design = if (perf_stat) |summary| capture.perfstat.measurementDesign(summary) else null; const group_count = if (design) |value| std.math.cast(usize, value.event_group_count) orelse return error.InvalidProfilingJson else 1; if (design) |value| { if (value.execution_count != 0) { const designed_execution_count = std.math.cast( usize, value.execution_count, ) orelse return error.InvalidProfilingJson; if (designed_execution_count != executions.len) { return error.InvalidProfilingJson; } } } if (group_count <= 1) { for (executions, 0..) |execution, index| { scratch[index] = @floatFromInt(execution.wall_ns); } return scratch[0..executions.len]; } const actual_design = design.?; const repetition_count = std.math.cast( usize, actual_design.repetition_count, ) orelse return error.InvalidProfilingJson; const expected_execution_count = std.math.mul( usize, group_count, repetition_count, ) catch return error.InvalidProfilingJson; if (repetition_count == 0 or expected_execution_count != executions.len) { return error.InvalidProfilingJson; } for (0..repetition_count) |repetition_index| { const start = repetition_index * group_count; var total: u128 = 0; for (executions[start .. start + group_count]) |execution| { total += execution.wall_ns; } scratch[repetition_index] = @as(f64, @floatFromInt(total)) / @as(f64, @floatFromInt(group_count)); } return scratch[0..repetition_count];}fn rawWallDistribution( executions: []const Execution, perf_stat: ?capture.perfstat.Summary,) !WallDistribution { var scratch: [host.process.max_executions]f64 = undefined; const samples = try wallEffectSamples(&scratch, executions, perf_stat); std.debug.assert(samples.len > 0); std.mem.sort(f64, samples, {}, std.sort.asc(f64)); const stats = capture.compare.effect.sampleStats(samples); const mean = stats.mean; const grouped = if (perf_stat) |summary| capture.perfstat.measurementDesign(summary).event_group_count > 1 else false; return .{ .kind = if (grouped) .grouped_repetition_means else .raw_executions, .sample_count = samples.len, .mean_ns = mean, .min_ns = samples[0], .median_ns = stats.median, .p95_ns = stats.p95, .p99_ns = stats.p99, .max_ns = samples[samples.len - 1], .stddev_ns = stats.stddev, .coefficient_of_variation_percent = if (mean == 0) null else (stats.stddev / @abs(mean)) * 100, };}fn summaryWallDistribution( mean_ns: f64, execution_count: usize, perf_stat: ?capture.perfstat.Summary,) WallDistribution { if (execution_count == 1) return .{ .kind = .point_estimate, .sample_count = 1, .mean_ns = mean_ns, }; const sample_count = if (perf_stat) |summary| sample_count: { const repetitions = std.math.cast( usize, capture.perfstat.measurementDesign(summary).repetition_count, ) orelse execution_count; break :sample_count if (repetitions == 0) execution_count else repetitions; } else execution_count; return .{ .kind = .legacy_summary, .sample_count = @max(sample_count, 1), .mean_ns = mean_ns, };}pub fn loadPerfStatSummary( allocator: std.mem.Allocator, captures: []const host.Capture,) !?capture.perfstat.Summary { for (captures) |row| { if (!std.mem.eql(u8, row.kind, host.counters.kind)) continue; if (!std.mem.eql(u8, row.state, "summary_written")) continue; return capture.perfstat.parseSummaryFile(allocator, row.summary_path) catch |err| switch (err) { error.FileNotFound => null, else => |actual| actual, }; } return null;}pub fn comparisonSupport( baseline: ComparisonInput, candidate: ComparisonInput,) ComparisonSupport { if (!std.mem.eql(u8, baseline.scope, candidate.scope)) return .scope_mismatch; if (!order.sameDesign(baseline.acquisition, candidate.acquisition)) { return .measurement_order_mismatch; } if (baseline.warmup_count != candidate.warmup_count) { return .warmup_design_mismatch; } if (!sameCaptureDesign(baseline.captures, candidate.captures)) { return .capture_mismatch; } if (!sameCapturePerturbationDesign( baseline.capture_perturbation, candidate.capture_perturbation, )) { return .capture_perturbation_mismatch; } const baseline_counter_capture = hasCaptureKind( baseline.captures, host.counters.kind, ); const candidate_counter_capture = hasCaptureKind( candidate.captures, host.counters.kind, ); if (!baseline_counter_capture and !candidate_counter_capture) return .supported; const baseline_perf_stat = baseline.perf_stat orelse return .perf_stat_summary_missing; const candidate_perf_stat = candidate.perf_stat orelse return .perf_stat_summary_missing; if (!sameCounterEvents(baseline_perf_stat, candidate_perf_stat)) { return .perf_stat_events_mismatch; } if (!capture.compare.samePerfStatEventGroups( baseline_perf_stat, candidate_perf_stat, )) { return .perf_stat_groups_mismatch; } if (capture.compare.perfStatMeasurementDesignChanged( capture.perfstat.measurementDesign(baseline_perf_stat), capture.perfstat.measurementDesign(candidate_perf_stat), )) { return .perf_stat_design_mismatch; } return .supported;}fn sameCapturePerturbationDesign( baseline: ?perturbation.Configuration, candidate: ?perturbation.Configuration,) bool { const base = baseline orelse return candidate == null; const actual = candidate orelse return false; if (base.tracy != actual.tracy or base.allocations != actual.allocations) { return false; } const base_host = base.host_kind orelse return actual.host_kind == null; const actual_host = actual.host_kind orelse return false; return std.mem.eql(u8, base_host, actual_host);}fn meanExecutionWallNs(executions: []const Execution) u64 { std.debug.assert(executions.len > 0); return totalWallNs(executions) / executions.len;}pub fn totalWallNs(executions: []const Execution) u64 { var total: u64 = 0; for (executions) |execution| total +|= execution.wall_ns; return total;}fn meanExecutionOptionalF64( executions: []const Execution, comptime field: enum { user_s, system_s },) ?f64 { std.debug.assert(executions.len > 0); var total: f64 = 0; for (executions) |execution| { total += @field(execution, @tagName(field)) orelse return null; } return total / @as(f64, @floatFromInt(executions.len));}fn meanExecutionOptionalU64( executions: []const Execution, comptime field: ResourceCountField,) ?f64 { std.debug.assert(executions.len > 0); var total: u64 = 0; for (executions) |execution| { total +|= @field(execution, @tagName(field)) orelse return null; } return @as(f64, @floatFromInt(total)) / @as(f64, @floatFromInt(executions.len));}fn commonResourceUsageSource( executions: []const Execution,) !?sys.process.ResourceUsageSource { std.debug.assert(executions.len > 0); const source = executions[0].resource_usage_source; for (executions) |execution| { if (execution.resource_usage_source != source) return error.InvalidProfilingJson; if (source == null and executionHasResourceCounts(execution)) { return error.InvalidProfilingJson; } } return source;}fn executionHasResourceCounts(execution: Execution) bool { return execution.minor_page_faults != null or execution.major_page_faults != null or execution.voluntary_context_switches != null or execution.involuntary_context_switches != null;}fn validateResourceTotals(resources: ResourceTotals) !void { if (resources.source != null) return; if (resources.minor_page_faults != null or resources.major_page_faults != null or resources.voluntary_context_switches != null or resources.involuntary_context_switches != null) { return error.InvalidProfilingJson; }}fn divideOptionalF64(value: ?f64, divisor: f64) ?f64 { return (value orelse return null) / divisor;}fn sameCaptureDesign( baseline_captures: []const host.Capture, candidate_captures: []const host.Capture,) bool { if (baseline_captures.len != candidate_captures.len) return false; for (baseline_captures, candidate_captures) |baseline_capture, candidate_capture| { if (!std.mem.eql(u8, baseline_capture.kind, candidate_capture.kind)) return false; if (!std.mem.eql(u8, baseline_capture.tool, candidate_capture.tool)) return false; if (!sameOptionalText( baseline_capture.tool_version, candidate_capture.tool_version, )) return false; if (!std.mem.eql(u8, baseline_capture.scope, candidate_capture.scope)) return false; if (captureApplied(baseline_capture) != captureApplied(candidate_capture)) return false; } return true;}fn testExecutionArtifactJson( allocator: std.mem.Allocator, index: usize, pid: u64, position: usize, root: []const u8,) ![]const u8 { return try std.fmt.allocPrint( allocator, "{{\"index\":{d},\"acquisition_position\":{d}," ++ "\"spawn_state\":\"spawned\",\"pid\":{d}," ++ "\"exit_code\":0,\"wall_ns\":{d},\"artifacts\":{{" ++ "\"root\":\"{s}\",\"stdout\":\"{s}/stdout.txt\"," ++ "\"stderr\":\"{s}/stderr.txt\",\"bench_jsonl\":\"{s}/bench.jsonl\"," ++ "\"coz_jsonl\":\"{s}/bench.coz.jsonl\"," ++ "\"coz_analysis\":\"{s}/bench.coz.analysis.json\"," ++ "\"tracy_jsonl\":\"{s}/bench.tracy.jsonl\"," ++ "\"tracy_summary\":\"{s}/bench.tracy.summary.jsonl\"," ++ "\"allocations\":\"{s}/allocations.jsonl\"," ++ "\"structured\":\"{s}/structured.jsonl\"," ++ "\"structured_rows\":{d},\"structured_parse_errors\":0}}}}", .{ index, position, pid, index * 10, root, root, root, root, root, root, root, root, root, root, index, }, );}test "profiling measurement retains measured execution artifacts" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const first = try testExecutionArtifactJson( allocator, 1, 101, 4, "run/workloads/w/executions/001", ); const second = try testExecutionArtifactJson( allocator, 2, 102, 9, "run/workloads/w/executions/002", ); const text = try std.fmt.allocPrint( allocator, "{{\"measurement\":{{\"execution_count\":2," ++ "\"workload_output_retention\":\"all_measured_executions\"," ++ "\"measured_artifact_layout\":\"numbered_execution_directories\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{s},{s}]}}}}", .{ first, second }, ); const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, text, .{}, ); const executions = try parseExecutions( allocator, try json.object(value), "run/workloads/w", ); try std.testing.expectEqual(@as(usize, 2), executions.len); try std.testing.expectEqual(@as(?u64, 101), executions[0].pid); try std.testing.expectEqual(@as(?usize, 4), executions[0].acquisition_position); try std.testing.expect(std.mem.endsWith( u8, executions[0].artifacts.?.structured, "/001/structured.jsonl", )); try std.testing.expectEqual(@as(usize, 2), executions[1].artifacts.?.structured_rows);}test "profiling measurement rejects invalid measured execution artifacts" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const missing = try std.json.parseFromSliceLeaky( std.json.Value, allocator, "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"all_measured_executions\"," ++ "\"measured_artifact_layout\":\"workload_root\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"spawn_state\":\"spawned\"," ++ "\"pid\":101," ++ "\"exit_code\":0,\"wall_ns\":10}]}}", .{}, ); try std.testing.expectError( error.InvalidProfilingJson, parseExecutions(allocator, try json.object(missing), "run/workloads/w"), ); const first = try testExecutionArtifactJson( allocator, 1, 101, 1, "run/workloads/w/executions/001", ); const second = try testExecutionArtifactJson( allocator, 2, 102, 2, "run/workloads/w/executions/001", ); const duplicate_text = try std.fmt.allocPrint( allocator, "{{\"measurement\":{{\"execution_count\":2," ++ "\"workload_output_retention\":\"all_measured_executions\"," ++ "\"measured_artifact_layout\":\"numbered_execution_directories\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{s},{s}]}}}}", .{ first, second }, ); const duplicate = try std.json.parseFromSliceLeaky( std.json.Value, allocator, duplicate_text, .{}, ); try std.testing.expectError( error.InvalidProfilingJson, parseExecutions(allocator, try json.object(duplicate), "run/workloads/w"), );}test "profiling measurement rejects legacy retention and invalid process identity" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); inline for (.{ "{\"measurement\":{\"execution_count\":0," ++ "\"workload_output_retention\":\"last_execution\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\",\"executions\":[]}}", "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"profiler_capture_contract\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"spawn_state\":\"spawned\"," ++ "\"pid\":0,\"exit_code\":0,\"wall_ns\":1}]}}", "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"profiler_capture_contract\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"spawn_state\":\"spawned\"," ++ "\"exit_code\":0,\"wall_ns\":1}]}}", "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"profiler_capture_contract\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"spawn_state\":\"spawned\"," ++ "\"pid\":\"101\",\"exit_code\":0,\"wall_ns\":1}]}}", "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"profiler_capture_contract\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"spawn_state\":\"spawn_failed\"," ++ "\"exit_code\":127,\"wall_ns\":1}]}}", "{\"measurement\":{\"execution_count\":1," ++ "\"workload_output_retention\":\"profiler_capture_contract\"," ++ "\"measured_artifact_layout\":\"none\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{\"index\":1,\"acquisition_position\":\"1\"," ++ "\"spawn_state\":\"spawned\",\"pid\":101," ++ "\"exit_code\":0,\"wall_ns\":1}]}}", }) |text| { const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, text, .{}, ); try std.testing.expectError( error.InvalidProfilingJson, parseExecutions(allocator, try json.object(value), "workloads/w"), ); }}test "profiling measurement accepts explicit spawn failure artifact receipt" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const spawned = try testExecutionArtifactJson( allocator, 1, 101, 1, "workloads/w/executions/001", ); const failed = try std.mem.replaceOwned( u8, allocator, spawned, "\"spawn_state\":\"spawned\",\"pid\":101,\"exit_code\":0", "\"spawn_state\":\"spawn_failed\",\"pid\":null,\"exit_code\":127", ); const text = try std.fmt.allocPrint( allocator, "{{\"measurement\":{{\"execution_count\":1," ++ "\"workload_output_retention\":\"all_measured_executions\"," ++ "\"measured_artifact_layout\":\"numbered_execution_directories\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{s}]}}}}", .{failed}, ); const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, text, .{}, ); const rows = try parseExecutions( allocator, try json.object(value), "workloads/w", ); try std.testing.expectEqual(@as(usize, 1), rows.len); try std.testing.expect(rows[0].pid == null); try std.testing.expectEqual(@as(i64, 127), rows[0].exit_code);}test "profiling measurement rejects aliased artifact filenames" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const valid = try testExecutionArtifactJson( allocator, 1, 101, 1, "workloads/w", ); const aliased = try std.mem.replaceOwned( u8, allocator, valid, "\"stdout\":\"workloads/w/stdout.txt\"", "\"stdout\":\"workloads/w/stderr.txt\"", ); const text = try std.fmt.allocPrint( allocator, "{{\"measurement\":{{\"execution_count\":1," ++ "\"workload_output_retention\":\"all_measured_executions\"," ++ "\"measured_artifact_layout\":\"workload_root\"," ++ "\"allocation_summary_retention\":\"disabled\"," ++ "\"executions\":[{s}]}}}}", .{aliased}, ); const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, text, .{}, ); try std.testing.expectError( error.InvalidProfilingJson, parseExecutions(allocator, try json.object(value), "workloads/w"), );}fn sameOptionalText(baseline: ?[]const u8, candidate: ?[]const u8) bool { const baseline_value = baseline orelse return candidate == null; const candidate_value = candidate orelse return false; return std.mem.eql(u8, baseline_value, candidate_value);}fn captureApplied(row: host.Capture) bool { return !std.mem.eql(u8, row.state, "tool_missing") and !std.mem.eql(u8, row.state, "binary_missing");}fn hasCaptureKind(captures: []const host.Capture, kind: []const u8) bool { for (captures) |row| { if (std.mem.eql(u8, row.kind, kind)) return true; } return false;}fn sameCounterEvents( baseline_summary: capture.perfstat.Summary, candidate_summary: capture.perfstat.Summary,) bool { if (baseline_summary.counters.len != candidate_summary.counters.len) return false; for (baseline_summary.counters) |baseline_counter| { var found = false; for (candidate_summary.counters) |candidate_counter| { if (std.mem.eql(u8, baseline_counter.event, candidate_counter.event)) { found = true; break; } } if (!found) return false; } return true;}test "profiling measurement retains process executions and computes means" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, \\{"measurement":{"execution_count":2, \\ "workload_output_retention":"profiler_capture_contract", \\ "measured_artifact_layout":"none", \\ "allocation_summary_retention":"disabled","executions":[ \\{"index":1,"spawn_state":"spawned","pid":101,"exit_code":0, \\ "wall_ns":10,"resource_usage_source":"wait4_rusage", \\ "max_rss_kib":20,"user_s":0.1,"system_s":0.2,"minor_page_faults":8, \\ "major_page_faults":0,"voluntary_context_switches":2, \\ "involuntary_context_switches":1}, \\{"index":2,"spawn_state":"spawned","pid":102,"exit_code":0, \\ "wall_ns":30,"resource_usage_source":"wait4_rusage", \\ "max_rss_kib":30,"user_s":0.3,"system_s":0.4,"minor_page_faults":12, \\ "major_page_faults":2,"voluntary_context_switches":4, \\ "involuntary_context_switches":3}]}} , .{}, ); const executions = try parseExecutions(allocator, try json.object(value), "workloads/w"); const stats = try summarize(40, .{}, executions, null); try std.testing.expectEqual(@as(u64, 20), stats.wall_ns); try std.testing.expectEqual(@as(u64, 40), stats.total_wall_ns); try std.testing.expectEqual(@as(usize, 2), stats.execution_count); try std.testing.expectEqual(Distribution.raw_executions, stats.wall_distribution.kind); try std.testing.expectEqual(@as(usize, 2), stats.wall_distribution.sample_count); try std.testing.expectEqual(@as(f64, 10), stats.wall_distribution.min_ns.?); try std.testing.expectEqual(@as(f64, 30), stats.wall_distribution.max_ns.?); try std.testing.expectApproxEqAbs( @as(f64, 14.142135), stats.wall_distribution.stddev_ns.?, 0.000001, ); try std.testing.expectApproxEqAbs(@as(f64, 0.2), stats.user_s.?, 0.000001); try std.testing.expectApproxEqAbs(@as(f64, 0.3), stats.system_s.?, 0.000001); try std.testing.expectEqual( sys.process.ResourceUsageSource.wait4_rusage, stats.resource_usage_source.?, ); try std.testing.expectApproxEqAbs(@as(f64, 10), stats.minor_page_faults.?, 0.000001); try std.testing.expectApproxEqAbs(@as(f64, 1), stats.major_page_faults.?, 0.000001); try std.testing.expectApproxEqAbs(@as(f64, 3), stats.voluntary_context_switches.?, 0.000001); try std.testing.expectApproxEqAbs(@as(f64, 2), stats.involuntary_context_switches.?, 0.000001);}test "profiling measurement requires an agreed resource accounting source" { const executions = [_]Execution{ .{ .exit_code = 0, .wall_ns = 1, .resource_usage_source = .wait4_rusage, .minor_page_faults = 1, }, .{ .exit_code = 0, .wall_ns = 1, .minor_page_faults = 1 }, }; try std.testing.expectError( error.InvalidProfilingJson, summarize(2, .{}, &executions, null), ); try std.testing.expectError( error.InvalidProfilingJson, summarize(1, .{ .minor_page_faults = 1 }, &.{}, null), );}test "profiling measurement parses warmups without mixing measured executions" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, \\{"warmup":{"execution_count":2,"executions":[ \\{"index":1,"exit_code":0,"wall_ns":5}, \\{"index":2,"exit_code":0,"wall_ns":7}]}, \\ "measurement":{"execution_count":1, \\ "workload_output_retention":"profiler_capture_contract", \\ "measured_artifact_layout":"none", \\ "allocation_summary_retention":"disabled", \\ "executions":[{"index":1,"spawn_state":"spawned","pid":101, \\ "exit_code":0,"wall_ns":11}]}} , .{}, ); const object = try json.object(value); const warmups = try parseWarmups(allocator, object); const executions = try parseExecutions(allocator, object, "workloads/w"); try std.testing.expectEqual(@as(usize, 2), warmups.len); try std.testing.expectEqual(@as(u64, 12), totalWallNs(warmups)); try std.testing.expectEqual(@as(usize, 1), executions.len); try std.testing.expectEqual(@as(u64, 11), executions[0].wall_ns);}test "profiling measurement rejects different warmup designs" { try std.testing.expectEqual( ComparisonSupport.warmup_design_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .warmup_count = 1, .captures = &.{}, .perf_stat = null }, .{ .scope = host.direct_scope, .warmup_count = 2, .captures = &.{}, .perf_stat = null }, ), );}test "profiling measurement rejects different order contexts" { try std.testing.expectEqual( ComparisonSupport.measurement_order_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .acquisition = .{ .blocked = .{ .position = 2, .workload_count = 2, .predecessors = &.{"a"}, } }, .captures = &.{}, .perf_stat = null, }, .{ .scope = host.direct_scope, .acquisition = .{ .blocked = .{ .position = 2, .workload_count = 3, .predecessors = &.{"b"}, } }, .captures = &.{}, .perf_stat = null, }, ), ); try std.testing.expectEqual( ComparisonSupport.supported, comparisonSupport( .{ .scope = host.direct_scope, .acquisition = .{ .blocked = .{ .position = 2, .workload_count = 2, .predecessors = &.{"a"}, } }, .captures = &.{}, .perf_stat = null, }, .{ .scope = host.direct_scope, .acquisition = .{ .blocked = .{ .position = 2, .workload_count = 3, .predecessors = &.{"a"}, } }, .captures = &.{}, .perf_stat = null, }, ), );}test "profiling measurement compares independent compatible interleavings" { const baseline = ComparisonInput{ .scope = host.direct_scope, .acquisition = .{ .random_interleaved = .{ .seed = 1, .repeat_count = 2, .workload_count = 2, .selected_workloads = &.{ "a", "b" }, .positions = &.{ 1, 4 }, } }, .captures = &.{}, .perf_stat = null, }; const candidate = ComparisonInput{ .scope = host.direct_scope, .acquisition = .{ .random_interleaved = .{ .seed = 2, .repeat_count = 2, .workload_count = 2, .selected_workloads = &.{ "a", "b" }, .positions = &.{ 2, 3 }, } }, .captures = &.{}, .perf_stat = null, }; try std.testing.expectEqual( ComparisonSupport.supported, comparisonSupport(baseline, candidate), ); var changed_cohort = candidate; changed_cohort.acquisition.random_interleaved.selected_workloads = &.{ "a", "c" }; try std.testing.expectEqual( ComparisonSupport.measurement_order_mismatch, comparisonSupport(baseline, changed_cohort), );}test "profiling measurement collapses grouped executions by repetition" { const summary: capture.perfstat.Summary = .{ .csv_path = "perf.stat.csv", .event_groups = &.{ .{ .index = 1, .events = "instructions", .csv_path = "group.1.csv" }, .{ .index = 2, .events = "branches", .csv_path = "group.2.csv" }, }, .counter_stability = &.{.{ .event = "instructions", .samples = 3, .numeric_samples = 3, .value_min = 90, .value_mean = 100, .value_max = 110, .value_relative_range_percent = 20, .coverage_min_percent = 100, .coverage_mean_percent = 100, .coverage_max_percent = 100, .unobserved_max_percent = 0, }}, .caveats = &.{}, .counters = &.{.{ .event = "instructions", .value_text = "100", .value = 100, .unit = null, .counter_runtime = 100, .running_percent = 100, .metric_text = null, .metric = null, .metric_unit = null, .uncertainty = .{ .kind = "complete", .source = "perf_stat_repeat_summary", .coverage_percent = 100, .unobserved_percent = 0, .multiplexed = false, }, }}, }; const executions = [_]Execution{ .{ .exit_code = 0, .wall_ns = 10 }, .{ .exit_code = 0, .wall_ns = 30 }, .{ .exit_code = 0, .wall_ns = 20 }, .{ .exit_code = 0, .wall_ns = 40 }, .{ .exit_code = 0, .wall_ns = 30 }, .{ .exit_code = 0, .wall_ns = 50 }, }; var scratch: [host.process.max_executions]f64 = undefined; const samples = try wallEffectSamples(&scratch, &executions, summary); try std.testing.expectEqualSlices(f64, &.{ 20, 30, 40 }, samples); const stats = try summarize(180, .{}, &executions, summary); try std.testing.expectEqual(@as(u64, 30), stats.wall_ns); try std.testing.expectEqual(@as(usize, 6), stats.execution_count); try std.testing.expectEqual( Distribution.grouped_repetition_means, stats.wall_distribution.kind, ); try std.testing.expectEqual(@as(usize, 3), stats.wall_distribution.sample_count); try std.testing.expectEqual(@as(f64, 30), stats.wall_distribution.median_ns.?); try std.testing.expectEqual(@as(f64, 40), stats.wall_distribution.p95_ns.?); try std.testing.expectEqual(@as(f64, 10), stats.wall_distribution.stddev_ns.?);}test "profiling measurement rejects inconsistent counts and totals" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const count_value = try std.json.parseFromSliceLeaky( std.json.Value, allocator, \\{"measurement":{"execution_count":2, \\ "workload_output_retention":"profiler_capture_contract", \\ "measured_artifact_layout":"none", \\ "allocation_summary_retention":"disabled", \\ "executions":[{"index":1,"spawn_state":"spawned","pid":101, \\ "exit_code":0,"wall_ns":10}]}} , .{}, ); try std.testing.expectError( error.InvalidProfilingJson, parseExecutions(allocator, try json.object(count_value), "workloads/w"), ); const executions = [_]Execution{.{ .exit_code = 0, .wall_ns = 10 }}; try std.testing.expectError( error.InvalidProfilingJson, summarize(11, .{}, &executions, null), );}fn expectLegacyWallSummary( distribution: WallDistribution, sample_count: usize,) !void { try std.testing.expectEqual(Distribution.legacy_summary, distribution.kind); try std.testing.expectEqual(sample_count, distribution.sample_count); try std.testing.expect(distribution.stddev_ns == null);}test "profiling measurement rejects mismatched perf designs" { const counter = capture.perfstat.Counter{ .event = "instructions", .value_text = "100", .value = 100, .unit = null, .counter_runtime = 1000, .running_percent = 100, .metric_text = null, .metric = null, .metric_unit = null, .uncertainty = .{ .kind = "complete", .source = "running_percent", .coverage_percent = 100, .unobserved_percent = 0, .multiplexed = false, }, }; const counters = [_]capture.perfstat.Counter{counter}; const repeated_stability = [_]capture.perfstat.CounterStability{.{ .event = "instructions", .samples = 4, .numeric_samples = 4, .value_min = 99, .value_mean = 100, .value_max = 101, .value_relative_range_percent = 2, .coverage_min_percent = 100, .coverage_mean_percent = 100, .coverage_max_percent = 100, .unobserved_max_percent = 0, }}; const baseline_summary = capture.perfstat.Summary{ .csv_path = "baseline.csv", .caveats = &.{}, .counters = &counters, }; const candidate_summary = capture.perfstat.Summary{ .csv_path = "candidate.csv", .counter_stability = &repeated_stability, .caveats = &.{}, .counters = &counters, }; const baseline_capture = [_]host.Capture{.{ .kind = host.counters.kind, .tool = host.counters.tool, .capture_path = "baseline.csv", .summary_path = "baseline.json", .state = "summary_written", }}; const candidate_capture = [_]host.Capture{.{ .kind = host.counters.kind, .tool = host.counters.tool, .capture_path = "candidate.csv", .summary_path = "candidate.json", .state = "summary_written", }}; try std.testing.expectEqual( ComparisonSupport.perf_stat_design_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .captures = &baseline_capture, .perf_stat = baseline_summary }, .{ .scope = host.direct_scope, .captures = &candidate_capture, .perf_stat = candidate_summary }, ), ); const stats = try summarize(500, .{}, &.{}, candidate_summary); try std.testing.expectEqual(@as(u64, 125), stats.wall_ns); try std.testing.expectEqual(@as(usize, 4), stats.execution_count); try expectLegacyWallSummary(stats.wall_distribution, 4);}test "profiling measurement rejects mismatched capture identities" { const sampled_capture = [_]host.Capture{.{ .kind = host.sampling.kind, .tool = host.sampling.tool, .capture_path = "perf.data", .summary_path = "perf.symbols.summary.json", .state = "summary_written", }}; try std.testing.expectEqual( ComparisonSupport.capture_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null }, .{ .scope = host.direct_scope, .captures = &sampled_capture, .perf_stat = null }, ), ); const baseline_versioned = [_]host.Capture{.{ .kind = host.sampling.kind, .tool = host.sampling.tool, .tool_version = "perf version 1", .capture_path = "baseline.data", .summary_path = "baseline.summary.json", .state = "summary_written", }}; const candidate_versioned = [_]host.Capture{.{ .kind = host.sampling.kind, .tool = host.sampling.tool, .tool_version = "perf version 2", .capture_path = "candidate.data", .summary_path = "candidate.summary.json", .state = "summary_written", }}; try std.testing.expectEqual( ComparisonSupport.capture_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .captures = &baseline_versioned, .perf_stat = null }, .{ .scope = host.direct_scope, .captures = &candidate_versioned, .perf_stat = null }, ), ); try std.testing.expectEqual( ComparisonSupport.supported, comparisonSupport( .{ .scope = host.direct_scope, .captures = &sampled_capture, .perf_stat = null }, .{ .scope = host.direct_scope, .captures = &sampled_capture, .perf_stat = null }, ), );}test "profiling measurement rejects mismatched capture control designs" { try std.testing.expectEqual( ComparisonSupport.capture_perturbation_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null }, .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null, .capture_perturbation = .{ .tracy = true }, }, ), ); try std.testing.expectEqual( ComparisonSupport.capture_perturbation_mismatch, comparisonSupport( .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null, .capture_perturbation = .{ .host_kind = host.sampling.kind }, }, .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null, .capture_perturbation = .{ .host_kind = host.counters.kind }, }, ), ); try std.testing.expectEqual( ComparisonSupport.supported, comparisonSupport( .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null, .capture_perturbation = .{ .tracy = true }, }, .{ .scope = host.direct_scope, .captures = &.{}, .perf_stat = null, .capture_perturbation = .{ .tracy = true }, }, ), );}Source: src/profiling/root.zig:31
zig
pub const measurement = @import("measurement.zig");Complete caller list for measurement.comparisonSupport
7 direct callers.
tiny.profiling.analyze.compare.workloadComparisonSupport[function] atsrc/profiling/analyze/compare.zig:199src.profiling.measurement.test_profiling_measurement_compares_independent_compatible_interleavings[function] — test; no exact target atsrc/profiling/measurement.zig:1327in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_different_order_contexts[function] — test; no exact target atsrc/profiling/measurement.zig:1274in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_different_warmup_designs[function] — test; no exact target atsrc/profiling/measurement.zig:1264in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_mismatched_capture_control_designs[function] — test; no exact target atsrc/profiling/measurement.zig:1582in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_mismatched_capture_identities[function] — test; no exact target atsrc/profiling/measurement.zig:1535in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_mismatched_perf_designs[function] — test; no exact target atsrc/profiling/measurement.zig:1464in nearest public ownertiny.profiling.measurement
Complete caller list for measurement.parseExecutions
9 direct callers.
tiny.profiling.analyze.load.parseWorkload[function] atsrc/profiling/analyze/load.zig:263src.profiling.measurement.test_profiling_measurement_accepts_explicit_spawn_failure_artifact_receipt[function] — test; no exact target atsrc/profiling/measurement.zig:1048in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_parses_warmups_without_mixing_measured_executions[function] — test; no exact target atsrc/profiling/measurement.zig:1236in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_aliased_artifact_filenames[function] — test; no exact target atsrc/profiling/measurement.zig:1091in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_inconsistent_counts_and_totals[function] — test; no exact target atsrc/profiling/measurement.zig:1428in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_invalid_measured_execution_artifacts[function] — test; no exact target atsrc/profiling/measurement.zig:939in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_legacy_retention_and_invalid_process_identity[function] — test; no exact target atsrc/profiling/measurement.zig:994in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_retains_measured_execution_artifacts[function] — test; no exact target atsrc/profiling/measurement.zig:890in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_retains_process_executions_and_computes_means[function] — test; no exact target atsrc/profiling/measurement.zig:1166in nearest public ownertiny.profiling.measurement
Complete caller list for measurement.summarize
7 direct callers.
src.profiling.analyze.fixture.data.measuredTestWorkload[function] — private; no exact target atsrc/profiling/analyze/fixture/data.zig:427in nearest public ownersrc.profiling.analyze.fixture.datatiny.profiling.analyze.load.finalizeExecutionSummary[function] atsrc/profiling/analyze/load.zig:808src.profiling.measurement.test_profiling_measurement_collapses_grouped_executions_by_repetition[function] — test; no exact target atsrc/profiling/measurement.zig:1364in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_inconsistent_counts_and_totals[function] — test; no exact target atsrc/profiling/measurement.zig:1428in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_rejects_mismatched_perf_designs[function] — test; no exact target atsrc/profiling/measurement.zig:1464in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_requires_an_agreed_resource_accounting_source[function] — test; no exact target atsrc/profiling/measurement.zig:1216in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.test_profiling_measurement_retains_process_executions_and_computes_means[function] — test; no exact target atsrc/profiling/measurement.zig:1166in nearest public ownertiny.profiling.measurement
Complete call list for measurement.summarize
9 direct calls.
src.profiling.measurement.commonResourceUsageSource[function] — private; no exact target atsrc/profiling/measurement.zig:795in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.divideOptionalF64[function] — private; no exact target atsrc/profiling/measurement.zig:827in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.meanExecutionOptionalF64[function] — private; no exact target atsrc/profiling/measurement.zig:770in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.meanExecutionOptionalU64[function] — private; no exact target atsrc/profiling/measurement.zig:782in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.meanExecutionWallNs[function] — private; no exact target atsrc/profiling/measurement.zig:759in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.rawWallDistribution[function] — private; no exact target atsrc/profiling/measurement.zig:624in nearest public ownertiny.profiling.measurementsrc.profiling.measurement.summaryWallDistribution[function] — private; no exact target atsrc/profiling/measurement.zig:655in nearest public ownertiny.profiling.measurementtiny.profiling.measurement.totalWallNs[function] atsrc/profiling/measurement.zig:764src.profiling.measurement.validateResourceTotals[function] — private; no exact target atsrc/profiling/measurement.zig:816in nearest public ownertiny.profiling.measurement
Audit
| Definitions | 21 |
|---|---|
| Public names | 21 |
| Members | 68 |
| Version | 26.7.0 |
| Revision | daab053ee433 |