Skip to documentation
SLOP

tiny.zen.diagram.limits

Reference tiny.zen diagram limits

Defined in diagram.

API (20)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Called byCallstest sourcelib.zen.src.diagram.limitstest: capacity derivation is monotone...private sourcelib.zen.src.diagram.limitsadddiagram.limitslineScratchBytesprivate sourcelib.zen.src.diagram.limitsmuldiagram.limits.Capacityderive
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.zen.src.diagram.limitsadddiagram.limits.CapacitytotalBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.zen.src.diagram.ascii.testparseTestDocumentdiagram.limits.Capacityderivediagram.limitslineScratchBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.zen.src.diagram.ascii.testparseTestDocumenttest sourcelib.zen.src.diagram.limitstest: measure reports lines and bytes...diagram.spec.LineIteratorinitdiagram.spec.LineIteratornextdiagram.limitsmeasure
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.zen.src.diagram.limitstest: capacity derivation is monotone...test sourcelib.zen.src.diagram.limitstest: survey counts records by kind a...test sourcelib.zen.src.diagram.limitstest: survey rejects malformed lines ...diagram.spec.LineIteratorinitdiagram.spec.LineIteratornextdiagram.specrecordKindOfdiagram.limitssurvey
Static calls · unresolved targets: 0 · external targets: 3.

Source: lib/zen/src/diagram/limits.zig

zig
const std = @import("std");const root = @import("root.zig");const spec = root.spec;pub const line_scratch_factor: u64 = 64;pub const line_scratch_slack: u64 = 4096;pub const list_growth_factor: u64 = 2;pub const fields_json_bytes_min: u64 = 8;pub const category_slot_bytes: u64 = 48;pub const mark_output_bytes: u64 = 4096;pub const axes_output_bytes: u64 = 16384;pub const svg_chrome_bytes: u64 = 4096;pub const escape_factor: u64 = 6;pub const region_slack_bytes: u64 = 4096;pub const Measure = struct {    line_count: u64 = 0,    max_line_bytes: u64 = 0,    input_bytes: u64 = 0,};pub fn measure(jsonl: []const u8) Measure {    var measured = Measure{};    var lines = spec.LineIterator.init(jsonl);    while (lines.next()) |line| {        measured.line_count += 1;        measured.max_line_bytes = @max(measured.max_line_bytes, line.len);        measured.input_bytes += line.len;    }    return measured;}pub fn lineScratchBytes(max_line_bytes: u64) error{DiagramTooLarge}!u64 {    const scaled = std.math.mul(u64, max_line_bytes, line_scratch_factor) catch return error.DiagramTooLarge;    return std.math.add(u64, scaled, line_scratch_slack) catch return error.DiagramTooLarge;}pub const Limits = struct {    input_bytes: u64 = 0,    max_line_bytes: u64 = 0,    record_count: u64 = 0,    frame_records: u64 = 0,    scale_records: u64 = 0,    transform_records: u64 = 0,    data_records: u64 = 0,    data_line_bytes: u64 = 0,    channel_records: u64 = 0,    explicit_mark_records: u64 = 0,    scratch_high_water: u64 = 0,    pub fn marksUpper(self: Limits) error{DiagramTooLarge}!u64 {        const fanout = std.math.mul(u64, self.channel_records, self.data_records) catch return error.DiagramTooLarge;        return std.math.add(u64, self.explicit_mark_records, fanout) catch return error.DiagramTooLarge;    }    pub fn fanoutStringBytes(self: Limits) error{DiagramTooLarge}!u64 {        return std.math.mul(u64, self.channel_records, self.data_line_bytes) catch return error.DiagramTooLarge;    }};pub fn survey(line_scratch: []u8, jsonl: []const u8) !Limits {    var limits = Limits{};    var scratch = std.heap.FixedBufferAllocator.init(line_scratch);    var lines = spec.LineIterator.init(jsonl);    while (lines.next()) |line| {        scratch.reset();        var parsed = std.json.parseFromSlice(std.json.Value, scratch.allocator(), line, .{}) catch |err| switch (err) {            error.OutOfMemory => return error.OutOfMemory,            else => return error.InvalidJsonl,        };        defer parsed.deinit();        limits.record_count += 1;        limits.input_bytes += line.len;        limits.max_line_bytes = @max(limits.max_line_bytes, line.len);        switch (try spec.recordKindOf(parsed.value)) {            .frame => limits.frame_records += 1,            .scale => limits.scale_records += 1,            .transform => limits.transform_records += 1,            .data => {                limits.data_records += 1;                limits.data_line_bytes += line.len;            },            .mark => limits.channel_records += 1,            .bar, .point, .rule, .text, .box, .edge => limits.explicit_mark_records += 1,        }        limits.scratch_high_water = @max(limits.scratch_high_water, scratch.end_index);    }    return limits;}pub const Capacity = struct {    line_scratch_bytes: u64,    document_bytes: u64,    render_scratch_bytes: u64,    output_bytes: u64,    pub fn derive(limits: Limits) error{DiagramTooLarge}!Capacity {        const marks_upper = try limits.marksUpper();        const fanout_string_bytes = try limits.fanoutStringBytes();        const retained_string_bytes = try add(limits.input_bytes, fanout_string_bytes);        const mark_slots = try mul(marks_upper, @sizeOf(spec.Mark) * list_growth_factor);        const data_slots = try mul(limits.data_records, @sizeOf(spec.DataRow) * list_growth_factor);        const transform_slots = try mul(limits.transform_records, @sizeOf(spec.Transform) * list_growth_factor);        const field_count = try add(limits.data_line_bytes / fields_json_bytes_min, limits.data_records);        const field_slots = try mul(field_count, @sizeOf(spec.Field) * list_growth_factor);        var document_bytes = try add(mark_slots, data_slots);        document_bytes = try add(document_bytes, transform_slots);        document_bytes = try add(document_bytes, field_slots);        document_bytes = try add(document_bytes, retained_string_bytes);        document_bytes = try add(document_bytes, region_slack_bytes);        var render_scratch_bytes = try mul(marks_upper, category_slot_bytes);        render_scratch_bytes = try add(render_scratch_bytes, retained_string_bytes);        render_scratch_bytes = try add(render_scratch_bytes, limits.max_line_bytes);        render_scratch_bytes = try add(render_scratch_bytes, region_slack_bytes);        var output_bytes = try mul(marks_upper, mark_output_bytes);        output_bytes = try add(output_bytes, try mul(retained_string_bytes, escape_factor));        output_bytes = try add(output_bytes, axes_output_bytes);        output_bytes = try add(output_bytes, svg_chrome_bytes);        output_bytes = try add(output_bytes, region_slack_bytes);        return .{            .line_scratch_bytes = try lineScratchBytes(limits.max_line_bytes),            .document_bytes = document_bytes,            .render_scratch_bytes = render_scratch_bytes,            .output_bytes = output_bytes,        };    }    pub fn totalBytes(self: Capacity) error{DiagramTooLarge}!u64 {        var total = try add(self.line_scratch_bytes, self.document_bytes);        total = try add(total, self.render_scratch_bytes);        return try add(total, self.output_bytes);    }};fn add(a: u64, b: u64) error{DiagramTooLarge}!u64 {    return std.math.add(u64, a, b) catch error.DiagramTooLarge;}fn mul(a: u64, b: u64) error{DiagramTooLarge}!u64 {    return std.math.mul(u64, a, b) catch error.DiagramTooLarge;}test "measure reports lines and bytes over trimmed nonempty lines" {    const jsonl = "  {\"kind\":\"frame\"}  \n\n{\"kind\":\"point\",\"x\":1,\"y\":2}\n";    const measured = measure(jsonl);    try std.testing.expectEqual(@as(u64, 2), measured.line_count);    try std.testing.expectEqual(@as(u64, 16 + 28), measured.input_bytes);    try std.testing.expectEqual(@as(u64, 28), measured.max_line_bytes);}test "survey counts records by kind and tracks scratch high water" {    const jsonl =        \\{"kind":"frame","title":"T"}        \\{"kind":"scale","axis":"x","type":"log"}        \\{"kind":"transform","op":"stack"}        \\{"kind":"data","name":"d","x":"a","y":1}        \\{"kind":"data","name":"d","x":"b","y":2}        \\{"kind":"mark","type":"bar","data":"d","x":"x","y":"y"}        \\{"kind":"bar","x":"a","y":1}        \\{"kind":"edge","x1":0,"y1":0,"x2":1,"y2":1}    ;    var scratch: [8192]u8 = undefined;    const limits = try survey(&scratch, jsonl);    try std.testing.expectEqual(@as(u64, 8), limits.record_count);    try std.testing.expectEqual(@as(u64, 1), limits.frame_records);    try std.testing.expectEqual(@as(u64, 1), limits.scale_records);    try std.testing.expectEqual(@as(u64, 1), limits.transform_records);    try std.testing.expectEqual(@as(u64, 2), limits.data_records);    try std.testing.expectEqual(@as(u64, 1), limits.channel_records);    try std.testing.expectEqual(@as(u64, 2), limits.explicit_mark_records);    try std.testing.expect(limits.scratch_high_water > 0);    try std.testing.expect(limits.scratch_high_water <= scratch.len);    try std.testing.expectEqual(@as(u64, 4), try limits.marksUpper());}test "survey rejects malformed lines exactly as parse admission" {    var scratch: [8192]u8 = undefined;    try std.testing.expectError(error.InvalidJsonl, survey(&scratch, "not json"));    try std.testing.expectError(error.MissingKind, survey(&scratch, "{\"x\":1}"));    try std.testing.expectError(error.UnknownRecordKind, survey(&scratch, "{\"kind\":\"nope\"}"));    try std.testing.expectError(error.InvalidRecord, survey(&scratch, "[1,2]"));}test "capacity derivation is monotone in survey terms and rejects overflow" {    var scratch: [8192]u8 = undefined;    const small = try survey(&scratch, "{\"kind\":\"point\",\"x\":1,\"y\":2}");    const capacity = try Capacity.derive(small);    try std.testing.expect(capacity.document_bytes >= small.input_bytes);    try std.testing.expect(capacity.output_bytes >= mark_output_bytes);    try std.testing.expect(try capacity.totalBytes() > 0);    var overflowing = small;    overflowing.channel_records = std.math.maxInt(u64) / 2;    overflowing.data_records = std.math.maxInt(u64) / 2;    try std.testing.expectError(error.DiagramTooLarge, Capacity.derive(overflowing));}

Source: lib/zen/src/diagram/root.zig:8

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

Audit

Definitions21
Public names21
Members18
Version26.7.0
Revisiondaab053ee433