Skip to documentation
SLOP

tiny.profiling.experiment.acquire

Reference tiny.profiling experiment acquire

Defined in experiment.

API (11)

Actions

Public operations.

Types and contracts

Public types and contracts.

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

Source

Called byCallsNo direct callsexperiment.runexecuteexperiment.acquire.Runnerdeinit
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsexperiment.runexecuteprivate; no linksrc.profiling.experiment.acquireprepareSideexperiment.acquire.Runnerinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersprivate; no linksrc.profiling.experiment.acquire.RunnerrunPairexperiment.acquirescheduleexperiment.acquire.RunnerrunPhase
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersprivate; no linksrc.profiling.experiment.acquirerunOptionalCommandexperiment.acquire.Runnersetup
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsexperiment.acquire.RunnerrunPhasetest; no linksrc.profiling.experiment.acquiretest: profiling experiment pair order...experiment.acquireschedule
Static calls · unresolved targets: 0 · external targets: 3.

Source: src/profiling/experiment/acquire.zig

zig
const std = @import("std");const sys = @import("sys");const profiling = @import("../root.zig");const model = @import("model.zig");const oracle = @import("oracle.zig");const variant = @import("variant.zig");const execute = profiling.execute;const host = profiling.host;const scenario = profiling.scenario;pub const PairOrder = enum {    baseline_first,    candidate_first,};pub const CommandResult = struct {    command: []const u8,    cwd: ?[]const u8,    stdout_path: []const u8,    stderr_path: []const u8,    execution: execute.Result,};pub const Observation = struct {    sequence: usize,    phase: model.Phase,    pair_index: usize,    position_in_pair: usize,    pair_order: PairOrder,    side: model.Side,    command: []const u8,    cwd: ?[]const u8,    reset: ?CommandResult,    stdout_path: []const u8,    stderr_path: []const u8,    execution: execute.Result,    metric_value: ?f64,    oracle: oracle.Result,    host_state: host.state.Window,    support: model.Support,};pub const PhaseOutcome = struct {    observations: []const Observation,    orders: []const PairOrder,    baseline_values: []const f64,    candidate_values: []const f64,    support: model.Support,    pub fn complete(self: PhaseOutcome) bool {        return self.support == .supported and            self.baseline_values.len == self.orders.len and            self.candidate_values.len == self.orders.len;    }};const SideRuntime = struct {    prepared: variant.Prepared,    measured: scenario.Command,    setup: ?scenario.Command,    reset: ?scenario.Command,    environment: sys.process.Environ.Map,};const PairOutcome = struct {    support: model.Support,    observation_count: usize,};const OutputPaths = struct {    stdout: []const u8,    stderr: []const u8,};const Measurement = struct {    command: []const u8,    paths: OutputPaths,    execution: execute.Result,    metric_value: ?f64,    oracle: oracle.Result,    host_state: host.state.Window,    support: model.Support,};pub const Runner = struct {    allocator: std.mem.Allocator,    process_io: std.Io,    artifact_root: []const u8,    definition: scenario.Definition,    metric: model.Metric,    baseline: SideRuntime,    candidate: SideRuntime,    pub fn init(        allocator: std.mem.Allocator,        process_io: std.Io,        base_environment: ?*const sys.process.Environ.Map,        artifact_root: []const u8,        definition: scenario.Definition,        metric: model.Metric,        baseline: variant.Prepared,        candidate: variant.Prepared,    ) !Runner {        var baseline_runtime = try prepareSide(            allocator,            base_environment,            definition,            baseline,        );        errdefer baseline_runtime.environment.deinit();        const candidate_runtime = try prepareSide(            allocator,            base_environment,            definition,            candidate,        );        return .{            .allocator = allocator,            .process_io = process_io,            .artifact_root = artifact_root,            .definition = definition,            .metric = metric,            .baseline = baseline_runtime,            .candidate = candidate_runtime,        };    }    pub fn deinit(self: *Runner) void {        self.baseline.environment.deinit();        self.candidate.environment.deinit();    }    pub fn setup(self: *Runner) ![2]?CommandResult {        return .{            try runOptionalCommand(                self,                &self.baseline,                self.baseline.setup,                "variants/baseline/setup",            ),            try runOptionalCommand(                self,                &self.candidate,                self.candidate.setup,                "variants/candidate/setup",            ),        };    }    pub fn runPhase(        self: *Runner,        phase: model.Phase,        pair_count: usize,        seed: u64,        sequence_start: usize,    ) !PhaseOutcome {        if (pair_count < 2 or pair_count > model.maximum_pairs) {            return error.InvalidExperimentPairCount;        }        const orders = try schedule(self.allocator, pair_count, seed);        const observations = try self.allocator.alloc(            Observation,            pair_count * 2,        );        const baseline_values = try self.allocator.alloc(f64, pair_count);        const candidate_values = try self.allocator.alloc(f64, pair_count);        var observation_count: usize = 0;        var completed_pairs: usize = 0;        var support = model.Support.supported;        for (orders, 0..) |order, pair_index| {            const pair = try self.runPair(                phase,                pair_index,                order,                sequence_start + observation_count,                observations[observation_count..],                &baseline_values[pair_index],                &candidate_values[pair_index],            );            support = pair.support;            observation_count += pair.observation_count;            if (support != .supported) break;            completed_pairs += 1;        }        return .{            .observations = observations[0..observation_count],            .orders = orders,            .baseline_values = baseline_values[0..completed_pairs],            .candidate_values = candidate_values[0..completed_pairs],            .support = support,        };    }    fn runPair(        self: *Runner,        phase: model.Phase,        pair_index: usize,        order: PairOrder,        sequence_start: usize,        observations: []Observation,        baseline_value: *f64,        candidate_value: *f64,    ) !PairOutcome {        std.debug.assert(observations.len >= 2);        const sides = switch (order) {            .baseline_first => [2]model.Side{ .baseline, .candidate },            .candidate_first => [2]model.Side{ .candidate, .baseline },        };        for (sides, 0..) |side, position| {            const observation = try self.runObservation(                phase,                pair_index,                position,                order,                side,                sequence_start + position,            );            observations[position] = observation;            if (observation.support != .supported) {                return .{                    .support = observation.support,                    .observation_count = position + 1,                };            }            const value = observation.metric_value.?;            switch (side) {                .baseline => baseline_value.* = value,                .candidate => candidate_value.* = value,            }        }        return .{ .support = .supported, .observation_count = 2 };    }    fn runObservation(        self: *Runner,        phase: model.Phase,        pair_index: usize,        position: usize,        order: PairOrder,        side: model.Side,        sequence: usize,    ) !Observation {        const runtime = self.runtimeFor(side);        const prefix = try observationPrefix(            self.allocator,            phase,            pair_index,            position,            side,        );        const reset = try runOptionalCommand(            self,            runtime,            runtime.reset,            try std.fmt.allocPrint(                self.allocator,                "observations/{s}.reset",                .{prefix},            ),        );        if (reset) |result| {            if (result.execution.exit_code != 0) {                return try failedResetObservation(                    self,                    runtime,                    phase,                    pair_index,                    position,                    order,                    side,                    sequence,                    result,                );            }        }        return try self.measure(            runtime,            phase,            pair_index,            position,            order,            side,            sequence,            prefix,            reset,        );    }    fn measure(        self: *Runner,        runtime: *SideRuntime,        phase: model.Phase,        pair_index: usize,        position: usize,        order: PairOrder,        side: model.Side,        sequence: usize,        prefix: []const u8,        reset: ?CommandResult,    ) !Observation {        const measurement = try self.captureMeasurement(            runtime,            prefix,        );        return .{            .sequence = sequence + 1,            .phase = phase,            .pair_index = pair_index + 1,            .position_in_pair = position + 1,            .pair_order = order,            .side = side,            .command = measurement.command,            .cwd = runtime.measured.cwd,            .reset = reset,            .stdout_path = measurement.paths.stdout,            .stderr_path = measurement.paths.stderr,            .execution = measurement.execution,            .metric_value = measurement.metric_value,            .oracle = measurement.oracle,            .host_state = measurement.host_state,            .support = measurement.support,        };    }    fn captureMeasurement(        self: *Runner,        runtime: *SideRuntime,        prefix: []const u8,    ) !Measurement {        const paths = try outputPaths(            self.allocator,            self.artifact_root,            try std.fmt.allocPrint(                self.allocator,                "observations/{s}",                .{prefix},            ),        );        const before = host.state.capture();        const execution = try execute.runCommand(            self.process_io,            &runtime.environment,            runtime.measured.cwd,            runtime.measured.argv,            paths.stdout,            paths.stderr,        );        const after = host.state.capture();        const verification = try oracle.verify(            self.allocator,            self.definition.oracle,            variant.substitutions(runtime.prepared),            runtime.measured.cwd,            execution.exit_code,            paths.stdout,            paths.stderr,        );        const metric_value = metricValue(self.metric, execution);        const support: model.Support = if (!verification.passed)            .oracle_failed        else if (metric_value == null)            .metric_unavailable        else if (!validMetric(metric_value.?))            .invalid_metric_value        else            .supported;        return .{            .command = try execute.commandText(                self.allocator,                runtime.measured.cwd,                null,                runtime.measured.argv,            ),            .paths = paths,            .execution = execution,            .metric_value = metric_value,            .oracle = verification,            .host_state = .{                .condition = .measurement,                .before = before,                .after = after,            },            .support = support,        };    }    fn runtimeFor(self: *Runner, selected: model.Side) *SideRuntime {        return switch (selected) {            .baseline => &self.baseline,            .candidate => &self.candidate,        };    }};fn failedResetObservation(    runner: *Runner,    runtime: *SideRuntime,    phase: model.Phase,    pair_index: usize,    position: usize,    order: PairOrder,    side: model.Side,    sequence: usize,    reset: CommandResult,) !Observation {    const empty = try emptyOracle(runner.allocator, reset);    return .{        .sequence = sequence + 1,        .phase = phase,        .pair_index = pair_index + 1,        .position_in_pair = position + 1,        .pair_order = order,        .side = side,        .command = try execute.commandText(            runner.allocator,            runtime.measured.cwd,            null,            runtime.measured.argv,        ),        .cwd = runtime.measured.cwd,        .reset = reset,        .stdout_path = reset.stdout_path,        .stderr_path = reset.stderr_path,        .execution = reset.execution,        .metric_value = null,        .oracle = empty,        .host_state = .{            .condition = .measurement,            .before = host.state.capture(),            .after = host.state.capture(),        },        .support = .reset_failed,    };}fn emptyOracle(    allocator: std.mem.Allocator,    command: CommandResult,) !oracle.Result {    const empty_expected = scenario.Oracle{        .exit_code = command.execution.exit_code,    };    return try oracle.verify(        allocator,        empty_expected,        .{ .binary = "none", .root = ".", .side = "none" },        command.cwd,        command.execution.exit_code,        command.stdout_path,        command.stderr_path,    );}fn prepareSide(    allocator: std.mem.Allocator,    base_environment: ?*const sys.process.Environ.Map,    definition: scenario.Definition,    prepared: variant.Prepared,) !SideRuntime {    const measured = try variant.command(allocator, prepared, definition);    const values = variant.substitutions(prepared);    const setup = if (definition.setup) |command|        try scenario.resolveCommand(            allocator,            command,            prepared.default_cwd,            values,        )    else        null;    const reset = if (definition.reset) |command|        try scenario.resolveCommand(            allocator,            command,            prepared.default_cwd,            values,        )    else        null;    var environment = if (base_environment) |base|        try base.clone(allocator)    else        sys.process.Environ.Map.init(allocator);    const resolved_environment = try scenario.resolveEnvironment(        allocator,        definition.environment,        values,    );    for (resolved_environment) |entry| {        try environment.put(entry.name, entry.value);    }    return .{        .prepared = prepared,        .measured = measured,        .setup = setup,        .reset = reset,        .environment = environment,    };}fn runOptionalCommand(    runner: *Runner,    runtime: *SideRuntime,    command: ?scenario.Command,    relative_prefix: []const u8,) !?CommandResult {    const actual = command orelse return null;    const paths = try outputPaths(        runner.allocator,        runner.artifact_root,        relative_prefix,    );    const execution = try execute.runCommand(        runner.process_io,        &runtime.environment,        actual.cwd,        actual.argv,        paths.stdout,        paths.stderr,    );    return .{        .command = try execute.commandText(            runner.allocator,            actual.cwd,            null,            actual.argv,        ),        .cwd = actual.cwd,        .stdout_path = paths.stdout,        .stderr_path = paths.stderr,        .execution = execution,    };}fn outputPaths(    allocator: std.mem.Allocator,    artifact_root: []const u8,    relative_prefix: []const u8,) !OutputPaths {    const stdout = try std.fmt.allocPrint(        allocator,        "{s}/{s}.stdout.txt",        .{ artifact_root, relative_prefix },    );    const stderr = try std.fmt.allocPrint(        allocator,        "{s}/{s}.stderr.txt",        .{ artifact_root, relative_prefix },    );    if (std.fs.path.dirname(stdout)) |directory| {        try sys.fs.createDirPath(directory);    }    return .{ .stdout = stdout, .stderr = stderr };}fn observationPrefix(    allocator: std.mem.Allocator,    phase: model.Phase,    pair_index: usize,    position: usize,    side: model.Side,) ![]const u8 {    return try std.fmt.allocPrint(        allocator,        "{s}-{d:0>4}-{d}-{s}",        .{ @tagName(phase), pair_index + 1, position + 1, @tagName(side) },    );}fn metricValue(    metric: model.Metric,    execution: execute.Result,) ?f64 {    return switch (metric) {        .wall_ns => @floatFromInt(execution.wall_ns),        .max_rss_kib => if (execution.maxrss_kib) |value|            @floatFromInt(value)        else            null,    };}fn validMetric(value: f64) bool {    return std.math.isFinite(value) and value > 0;}pub fn schedule(    allocator: std.mem.Allocator,    pair_count: usize,    seed: u64,) ![]PairOrder {    if (pair_count < 2 or pair_count > model.maximum_pairs) {        return error.InvalidExperimentPairCount;    }    const orders = try allocator.alloc(PairOrder, pair_count);    var baseline_first_count = pair_count / 2;    if (pair_count % 2 != 0 and seed & 1 == 0) baseline_first_count += 1;    for (orders, 0..) |*order, index| {        order.* = if (index < baseline_first_count)            .baseline_first        else            .candidate_first;    }    var prng = std.Random.DefaultPrng.init(seed);    const random = prng.random();    var remaining = orders.len;    while (remaining > 1) {        const index = random.uintLessThan(usize, remaining);        remaining -= 1;        std.mem.swap(PairOrder, &orders[index], &orders[remaining]);    }    return orders;}test "profiling experiment pair order is deterministic and balanced" {    const first = try schedule(std.testing.allocator, 11, 42);    defer std.testing.allocator.free(first);    const second = try schedule(std.testing.allocator, 11, 42);    defer std.testing.allocator.free(second);    try std.testing.expectEqualSlices(PairOrder, first, second);    var baseline_first: usize = 0;    for (first) |order| {        if (order == .baseline_first) baseline_first += 1;    }    try std.testing.expect(        baseline_first == 5 or baseline_first == 6,    );}

Source: src/profiling/experiment/root.zig:1

zig
pub const acquire = @import("acquire.zig");

Audit

Definitions12
Public names12
Members35
Version26.7.0
Revisiondaab053ee433