tiny.bench.compare
Defined in tiny.bench.
API (36)
Actions
Public operations.
Classification.jsonNameSummaryComparisonanalyzeExecutionsanalyzeU64MediansduplicateObjectStringobjectBoolDefaultobjectNumberOptionalobjectStringOptionalobjectU64parseArgssummarizeExecutions
Types and contracts
Public types and contracts.
CapacityCapacityErrorClassificationComparisonStorageCountsEffectIntervalExecutionAnalysisOptionsExecutionComparisonExecutionObservationExecutionStatsLimitsOptionsStorageStorageErrorStorageExhaustionStorageStatusU64MedianRatio
Values and defaults
Public values and defaults.
bootstrap_seedconfidence_per_milledefault_bootstrap_iterationsdefault_min_runsdefault_thresholdeffect_confidenceeffect_methodmax_profile_bytes
Source
Source: lib/bench/src/compare/engine.zig:48
pub const Classification = enum { regression, improvement, unchanged, uncertain, insufficient, pub fn jsonName(self: Classification) []const u8 { return switch (self) { .regression => "regression", .improvement => "improvement", .unchanged => "unchanged", .uncertain => "uncertain", .insufficient => "insufficient", }; }};Source: lib/bench/src/compare/engine.zig:37
pub const Counts = struct { compared: u64 = 0, regressions: u64 = 0, improvements: u64 = 0, unchanged: u64 = 0, uncertain: u64 = 0, insufficient: u64 = 0, missing_baseline: u64 = 0, missing_candidate: u64 = 0,};Source: lib/bench/src/compare/engine.zig:66
pub const EffectInterval = struct { low_percent: f64, high_percent: f64,};Source: lib/bench/src/compare/engine.zig:84
pub const ExecutionAnalysisOptions = struct { threshold: f64 = default_threshold, min_runs: u32 = default_min_runs, bootstrap_iterations: u32 = default_bootstrap_iterations,};Source: lib/bench/src/compare/engine.zig:90
pub const ExecutionComparison = struct { classification: Classification, baseline: ExecutionStats, candidate: ExecutionStats, ratio: ?f64, effect: ?EffectInterval, bootstrap_iterations: u32, evidence: []const u8,};Source: lib/bench/src/compare/engine.zig:71
pub const ExecutionObservation = struct { mean: f64, median: f64,};Source: lib/bench/src/compare/engine.zig:76
pub const ExecutionStats = struct { runs: usize, mean: f64, median: f64, min: f64, max: f64,};Source: lib/bench/src/compare/engine.zig:29
pub const Options = struct { baseline_path: []const u8, candidate_path: []const u8, threshold: f64 = default_threshold, min_runs: u32 = default_min_runs, bootstrap_iterations: u32 = default_bootstrap_iterations,};Source: lib/bench/src/compare/engine.zig:100
pub const U64MedianRatio = struct { baseline_median: u64, candidate_median: u64, ratio: f64, low_ratio: f64, high_ratio: f64,};Source: lib/bench/src/compare/engine.zig:194
pub fn SummaryComparison(comptime Spec: type) type { return struct { pub fn runFiles( allocator: Allocator, out: *std.Io.Writer, args: []const []const u8, ) !u8 { return runComparisonFiles(Spec, allocator, out, args); } pub fn parseArgs(args: []const []const u8) !Options { return parseComparisonArgs(args); } pub fn compareSources( allocator: Allocator, out: *std.Io.Writer, options: Options, baseline_source: []const u8, candidate_source: []const u8, ) !Counts { return compareSummarySources( Spec, allocator, out, options, baseline_source, candidate_source, ); } };}Source: lib/bench/src/compare/engine.zig:595
pub fn analyzeExecutions( storage: *Storage, baseline: []const ExecutionObservation, candidate: []const ExecutionObservation, options: ExecutionAnalysisOptions,) !ExecutionComparison { if (!std.math.isFinite(options.threshold) or options.threshold < 1.0) { return error.InvalidThreshold; } if (options.min_runs == 0) return error.InvalidMinimumRuns; if (options.bootstrap_iterations == 0) return error.InvalidBootstrapIterations; if (baseline.len == 0 or candidate.len == 0) return error.EmptyExecutionSet; const regions = try storage.acquireF64( baseline.len, candidate.len, options.bootstrap_iterations, ); defer storage.reset(); const baseline_stats = try summarizeExecutionsInScratch( baseline, regions.samples[0..baseline.len], ); const candidate_stats = try summarizeExecutionsInScratch( candidate, regions.samples[0..candidate.len], ); const ratio = ratioOrNull(baseline_stats.median, candidate_stats.median); const enough = baseline.len >= options.min_runs and candidate.len >= options.min_runs; const effect = if (enough) try bootstrapMedianPercentChange(baseline, candidate, regions) else null; return .{ .classification = classifyChange(effect, enough, options.threshold), .baseline = baseline_stats, .candidate = candidate_stats, .ratio = ratio, .effect = effect, .bootstrap_iterations = options.bootstrap_iterations, .evidence = evidenceState(enough, effect), };}Source: lib/bench/src/compare/engine.zig:638
pub fn analyzeU64Medians( storage: *Storage, baseline: []const u64, candidate: []const u64, bootstrap_iterations: u32, seed: u64,) StorageError!U64MedianRatio { const regions = try storage.acquireU64( baseline.len, candidate.len, bootstrap_iterations, ); defer storage.reset(); const baseline_values = canonicalU64(baseline, regions.samples[0..baseline.len]); const baseline_median = upperMedianU64(baseline_values); const candidate_values = canonicalU64(candidate, regions.samples[0..candidate.len]); const candidate_median = upperMedianU64(candidate_values); var prng = std.Random.DefaultPrng.init(seed); const random = prng.random(); const bootstrap_baseline = canonicalU64(baseline, regions.samples[0..baseline.len]); fillBootstrapU64Medians( regions.effects, bootstrap_baseline, regions.counts[0..baseline.len], random, ); const bootstrap_candidate = canonicalU64(candidate, regions.samples[0..candidate.len]); for (regions.effects) |*ratio| { const candidate_value = bootstrapU64Median( bootstrap_candidate, regions.counts[0..candidate.len], random, ); ratio.* = u64RatioFloat(candidate_value, ratio.*); } std.mem.sort(f64, regions.effects, {}, std.sort.asc(f64)); const low_index = ratioQuantileIndex(regions.effects.len, 25); const high_index = ratioQuantileIndex(regions.effects.len, 975); return .{ .baseline_median = baseline_median, .candidate_median = candidate_median, .ratio = u64Ratio(candidate_median, baseline_median), .low_ratio = regions.effects[@min(low_index, regions.effects.len - 1)], .high_ratio = regions.effects[@min(high_index, regions.effects.len - 1)], };}Source: lib/bench/src/compare/engine.zig:22
pub const bootstrap_seed: u64 = 0x5449_4e59_434f_4d50;Source: lib/bench/src/compare/engine.zig:23
pub const confidence_per_mille: u16 = 950;Source: lib/bench/src/compare/engine.zig:21
pub const default_bootstrap_iterations: u32 = 1000;Source: lib/bench/src/compare/engine.zig:20
pub const default_min_runs: u32 = 10;Source: lib/bench/src/compare/engine.zig:19
pub const default_threshold = 1.05;Source: lib/bench/src/compare/engine.zig:971
pub fn duplicateObjectString( allocator: Allocator, object: std.json.ObjectMap, key: []const u8,) ![]u8 { const text = objectStringOptional(object, key) orelse return error.InvalidSummary; return try allocator.dupe(u8, text);}Source: lib/bench/src/compare/engine.zig:24
pub const effect_confidence: f64 = @as(f64, @floatFromInt(confidence_per_mille)) / 1000.0;Source: lib/bench/src/compare/engine.zig:26
pub const effect_method = "deterministic_percentile_bootstrap_unpaired_execution_median_percent_change";Source: lib/bench/src/compare/engine.zig:18
pub const max_profile_bytes = 64 * 1024 * 1024;Source: lib/bench/src/compare/engine.zig:1009
pub fn objectBoolDefault( object: std.json.ObjectMap, key: []const u8, default: bool,) !bool { const value = object.get(key) orelse return default; return switch (value) { .bool => |actual| actual, else => error.InvalidSummary, };}Source: lib/bench/src/compare/engine.zig:998
pub fn objectNumberOptional(object: std.json.ObjectMap, key: []const u8) ?f64 { const value = object.get(key) orelse return null; const number: f64 = switch (value) { .integer => |integer| @floatFromInt(integer), .float => |float| float, .number_string => |text| std.fmt.parseFloat(f64, text) catch return null, else => return null, }; return if (std.math.isFinite(number)) number else null;}Source: lib/bench/src/compare/engine.zig:980
pub fn objectStringOptional(object: std.json.ObjectMap, key: []const u8) ?[]const u8 { const value = object.get(key) orelse return null; return switch (value) { .string => |text| text, else => null, };}Source: lib/bench/src/compare/engine.zig:988
pub fn objectU64(object: std.json.ObjectMap, key: []const u8) !u64 { const value = object.get(key) orelse return error.InvalidSummary; return switch (value) { .integer => |integer| if (integer < 0) error.InvalidSummary else @intCast(integer), .number_string => |text| std.fmt.parseUnsigned(u64, text, 10) catch return error.InvalidSummary, else => error.InvalidSummary, };}Source: lib/bench/src/compare/engine.zig:110
fn parseComparisonArgs(args: []const []const u8) !Options { if (args.len < 2) return error.InvalidArguments; if (args[0].len == 0 or args[0][0] == '-') return error.InvalidArguments; if (args[1].len == 0 or args[1][0] == '-') return error.InvalidArguments; var options = Options{ .baseline_path = args[0], .candidate_path = args[1], }; var threshold_specified = false; var min_runs_specified = false; var bootstrap_iterations_specified = false; var index: usize = 2; while (index < args.len) : (index += 1) { const arg = args[index]; if (std.mem.eql(u8, arg, "--threshold")) { if (threshold_specified) return error.InvalidArguments; index += 1; if (index >= args.len) return error.InvalidArguments; options.threshold = parseThreshold(args[index]) catch return error.InvalidArguments; threshold_specified = true; } else if (std.mem.eql(u8, arg, "--min-runs")) { if (min_runs_specified) return error.InvalidArguments; index += 1; if (index >= args.len) return error.InvalidArguments; options.min_runs = std.fmt.parseUnsigned(u32, args[index], 10) catch return error.InvalidArguments; if (options.min_runs == 0) return error.InvalidArguments; min_runs_specified = true; } else if (std.mem.eql(u8, arg, "--bootstrap-iterations")) { if (bootstrap_iterations_specified) return error.InvalidArguments; index += 1; if (index >= args.len) return error.InvalidArguments; options.bootstrap_iterations = std.fmt.parseUnsigned(u32, args[index], 10) catch return error.InvalidArguments; if (options.bootstrap_iterations == 0) return error.InvalidArguments; bootstrap_iterations_specified = true; } else { return error.InvalidArguments; } } return options;}Source: lib/bench/src/compare/engine.zig:685
pub fn summarizeExecutions( storage: *Storage, observations: []const ExecutionObservation,) !ExecutionStats { if (observations.len == 0) return error.EmptyExecutionSet; const scratch = try storage.acquireF64Samples(observations.len); defer storage.reset(); return summarizeExecutionsInScratch(observations, scratch);}Source: lib/bench/src/compare/root.zig
const engine = @import("engine.zig");pub const Limits = engine.Limits;pub const Capacity = engine.Capacity;pub const CapacityError = engine.CapacityError;pub const Storage = engine.Storage;pub const StorageStatus = engine.StorageStatus;pub const StorageExhaustion = engine.StorageExhaustion;pub const StorageError = engine.StorageError;pub const max_profile_bytes = engine.max_profile_bytes;pub const default_threshold = engine.default_threshold;pub const default_min_runs = engine.default_min_runs;pub const default_bootstrap_iterations = engine.default_bootstrap_iterations;pub const bootstrap_seed = engine.bootstrap_seed;pub const confidence_per_mille = engine.confidence_per_mille;pub const effect_confidence = engine.effect_confidence;pub const effect_method = engine.effect_method;pub const Options = engine.Options;pub const Counts = engine.Counts;pub const Classification = engine.Classification;pub const EffectInterval = engine.EffectInterval;pub const ExecutionObservation = engine.ExecutionObservation;pub const ExecutionStats = engine.ExecutionStats;pub const ExecutionAnalysisOptions = engine.ExecutionAnalysisOptions;pub const ExecutionComparison = engine.ExecutionComparison;pub const U64MedianRatio = engine.U64MedianRatio;pub const parseArgs = engine.parseArgs;pub const SummaryComparison = engine.SummaryComparison;pub const analyzeExecutions = engine.analyzeExecutions;pub const analyzeU64Medians = engine.analyzeU64Medians;pub const summarizeExecutions = engine.summarizeExecutions;pub const duplicateObjectString = engine.duplicateObjectString;pub const objectStringOptional = engine.objectStringOptional;pub const objectU64 = engine.objectU64;pub const objectNumberOptional = engine.objectNumberOptional;pub const objectBoolDefault = engine.objectBoolDefault;pub const ComparisonStorage = @import("storage.zig").Storage;Source: lib/bench/src/root.zig:121
pub const compare = compare_mod;Complete call list for compare.analyzeU64Medians
8 direct calls.
lib.bench.src.compare.engine.bootstrapU64Median[function] — private source atlib/bench/src/compare/engine.zig:893in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.canonicalU64[function] — private source atlib/bench/src/compare/engine.zig:867in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.fillBootstrapU64Medians[function] — private source atlib/bench/src/compare/engine.zig:880in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.ratioQuantileIndex[function] — private source atlib/bench/src/compare/engine.zig:940in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.u64Ratio[function] — private source atlib/bench/src/compare/engine.zig:914in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.u64RatioFloat[function] — private source atlib/bench/src/compare/engine.zig:920in nearest public ownerlib.bench.src.compare.enginelib.bench.src.compare.engine.upperMedianU64[function] — private source atlib/bench/src/compare/engine.zig:875in nearest public ownerlib.bench.src.compare.enginelib.trace.src.profiling.storage.reset[function] — private source atlib/trace/src/profiling/storage.zig:19in nearest public ownerlib.trace.src.profiling.storage
Audit
| Definitions | 29 |
|---|---|
| Public names | 29 |
| Members | 42 |
| Version | 26.7.0 |
| Revision | daab053ee433 |