tiny.profiling.ingest.capacity
Defined in ingest.
API (3)
Actions
Public operations.
Types and contracts
Public types and contracts.
Source
Source: src/profiling/ingest/capacity.zig
zig
const std = @import("std");const ingest = @import("root.zig");const model = ingest.model;const classify = ingest.classify;pub const Capacity = struct { facts: model.Facts, line_bytes: usize, row_bits: usize, row_bit_bytes: usize, json_stack_bytes: usize, key_bytes: usize, key_entries: usize, object_frames: usize, key_entries_offset: usize, object_frames_offset: usize, scratch_bytes: usize, working_bytes: usize, pub fn derive(limits: model.Limits) error{CapacityOverflow}!Capacity { std.debug.assert(limits.facts.sources.len == model.source_count); var line_bytes: usize = 0; var row_bits: usize = 0; var max_json_depth: usize = 0; var max_key_count: usize = 0; for (limits.facts.sources, 0..) |source, index| { std.debug.assert(index < model.source_count); if (source.present) { std.debug.assert(source.candidates <= source.lines); std.debug.assert(source.max_json_depth <= source.max_line_bytes); std.debug.assert(source.max_key_count <= source.max_line_bytes); } line_bytes = @max(line_bytes, source.max_line_bytes); max_json_depth = @max(max_json_depth, source.max_json_depth); max_key_count = @max(max_key_count, source.max_key_count); if (index < model.ordinary_source_count) { row_bits = add(row_bits, source.candidates) catch return error.CapacityOverflow; } } const row_bit_bytes = try bytesForBits(row_bits); const json_stack_bytes = try bytesForBits(max_json_depth); const key_entries_offset = try alignForward( try add(json_stack_bytes, line_bytes), @alignOf(classify.KeyEntry), ); const key_entry_bytes = try bytesFor(classify.KeyEntry, max_key_count); const object_frames_offset = try alignForward( try add(key_entries_offset, key_entry_bytes), @alignOf(classify.ObjectFrame), ); const object_frame_bytes = try bytesFor(classify.ObjectFrame, max_json_depth); const scratch_bytes = try add(object_frames_offset, object_frame_bytes); const working_bytes = try add(try add(line_bytes, row_bit_bytes), scratch_bytes); if (row_bits > 0) std.debug.assert(row_bit_bytes <= row_bits); if (max_json_depth > 0) std.debug.assert(json_stack_bytes <= max_json_depth); if (line_bytes > 0) std.debug.assert(max_key_count <= line_bytes); std.debug.assert(key_entries_offset >= json_stack_bytes + line_bytes); std.debug.assert(object_frames_offset >= key_entries_offset); std.debug.assert(scratch_bytes >= object_frames_offset); std.debug.assert(working_bytes >= line_bytes); std.debug.assert(working_bytes >= row_bit_bytes); std.debug.assert(working_bytes >= scratch_bytes); return .{ .facts = limits.facts, .line_bytes = line_bytes, .row_bits = row_bits, .row_bit_bytes = row_bit_bytes, .json_stack_bytes = json_stack_bytes, .key_bytes = line_bytes, .key_entries = max_key_count, .object_frames = max_json_depth, .key_entries_offset = key_entries_offset, .object_frames_offset = object_frames_offset, .scratch_bytes = scratch_bytes, .working_bytes = working_bytes, }; } pub fn scratch( self: Capacity, storage: []align(@alignOf(usize)) u8, ) classify.Scratch { std.debug.assert(storage.len == self.scratch_bytes); std.debug.assert(self.json_stack_bytes + self.key_bytes <= self.key_entries_offset); std.debug.assert(self.key_entries_offset <= self.object_frames_offset); std.debug.assert(self.object_frames_offset <= self.scratch_bytes); const keys_bytes = storage[self.key_entries_offset..self.object_frames_offset]; const frames_bytes = storage[self.object_frames_offset..self.scratch_bytes]; const result = classify.Scratch{ .json_stack = storage[0..self.json_stack_bytes], .key_bytes = storage[self.json_stack_bytes..][0..self.key_bytes], .keys = std.mem.bytesAsSlice( classify.KeyEntry, @as([]align(@alignOf(classify.KeyEntry)) u8, @alignCast(keys_bytes)), )[0..self.key_entries], .objects = std.mem.bytesAsSlice( classify.ObjectFrame, @as([]align(@alignOf(classify.ObjectFrame)) u8, @alignCast(frames_bytes)), )[0..self.object_frames], }; std.debug.assert(result.json_stack.len == self.json_stack_bytes); std.debug.assert(result.key_bytes.len == self.key_bytes); std.debug.assert(result.keys.len == self.key_entries); std.debug.assert(result.objects.len == self.object_frames); return result; }};fn bytesForBits(bits: usize) error{CapacityOverflow}!usize { const whole = bits / 8; std.debug.assert(whole <= bits); if (bits % 8 == 0) return whole; return add(whole, 1);}fn add(left: usize, right: usize) error{CapacityOverflow}!usize { return std.math.add(usize, left, right) catch error.CapacityOverflow;}fn bytesFor(comptime T: type, count: usize) error{CapacityOverflow}!usize { std.debug.assert(@sizeOf(T) > 0); return std.math.mul(usize, @sizeOf(T), count) catch error.CapacityOverflow;}fn alignForward(value: usize, alignment: usize) error{CapacityOverflow}!usize { std.debug.assert(std.math.isPowerOfTwo(alignment)); const mask = alignment - 1; const rounded = try add(value, mask); return rounded & ~mask;}fn modelIngestionWorkingBytes(facts: model.Facts) u128 { var line_bytes: u128 = 0; var row_bits: u128 = 0; var json_depth: u128 = 0; var key_count: u128 = 0; for (facts.sources, 0..) |source, index| { line_bytes = @max(line_bytes, source.max_line_bytes); json_depth = @max(json_depth, source.max_json_depth); key_count = @max(key_count, source.max_key_count); if (index < model.ordinary_source_count) row_bits += source.candidates; } const row_bytes = (row_bits + 7) / 8; const stack_bytes = (json_depth + 7) / 8; const key_offset = modelAlign(stack_bytes + line_bytes, @alignOf(classify.KeyEntry)); const frame_offset = modelAlign( key_offset + key_count * @sizeOf(classify.KeyEntry), @alignOf(classify.ObjectFrame), ); const scratch_bytes = frame_offset + json_depth * @sizeOf(classify.ObjectFrame); return line_bytes + row_bytes + scratch_bytes;}fn modelAlign(value: u128, alignment: u128) u128 { std.debug.assert(std.math.isPowerOfTwo(alignment)); return (value + alignment - 1) & ~(alignment - 1);}test "ingestion capacity matches an independent bit and scratch model" { comptime { @stardustClaim( @import("alloc_phase").capacity.witness(@import("./root.zig").ArtifactIngestion, "profiling_ingestion_capacity_capacity_model"), null, null, null, null, null, null, ); } comptime { @stardustClaim( @import("alloc_phase").capacity.witness(@import("./root.zig").ArtifactIngestion, "profiling_ingestion_capacity_overload"), null, null, null, null, null, null, ); } var facts = model.Facts{ .sources = @splat(.{}) }; facts.sources[0].candidates = 9; facts.sources[0].max_line_bytes = 41; facts.sources[0].max_json_depth = 8; facts.sources[0].max_key_count = 3; facts.sources[1].candidates = 7; facts.sources[1].max_line_bytes = 17; facts.sources[1].max_json_depth = 9; const capacity = try Capacity.derive(.{ .paths = undefined, .facts = facts }); try std.testing.expectEqual(@as(usize, 16), capacity.row_bits); try std.testing.expectEqual(@as(usize, 2), capacity.row_bit_bytes); try std.testing.expectEqual(@as(usize, 2), capacity.json_stack_bytes); try std.testing.expectEqual(@as(usize, 41), capacity.line_bytes); try std.testing.expectEqual(@as(usize, 3), capacity.key_entries); try std.testing.expectEqual(@as(usize, 9), capacity.object_frames); try std.testing.expect(capacity.scratch_bytes >= 43); try std.testing.expectEqual( capacity.line_bytes + capacity.row_bit_bytes + capacity.scratch_bytes, capacity.working_bytes, ); try std.testing.expectEqual( modelIngestionWorkingBytes(facts), capacity.working_bytes, );}test "ingestion capacity rejects unrepresentable candidate storage" { var facts = model.Facts{ .sources = @splat(.{}) }; facts.sources[0].candidates = std.math.maxInt(usize); facts.sources[1].candidates = 1; try std.testing.expectError( error.CapacityOverflow, Capacity.derive(.{ .paths = undefined, .facts = facts }), );}Source: src/profiling/ingest/root.zig:8
zig
pub const capacity = @import("capacity.zig");Audit
| Definitions | 4 |
|---|---|
| Public names | 7 |
| Members | 12 |
| Version | 26.7.0 |
| Revision | daab053ee433 |