Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smaller memory footprint for BoundedArray #16299

Merged
merged 4 commits into from
Jul 3, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions lib/std/bounded_array.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ pub fn BoundedArrayAligned(
) type {
return struct {
const Self = @This();
const Len = std.math.IntFittingRange(0, buffer_capacity);

buffer: [buffer_capacity]T align(alignment) = undefined,
len: usize = 0,
len: Len = 0,

/// Set the actual length of the slice.
/// Returns error.Overflow if it exceeds the length of the backing array.
pub fn init(len: usize) error{Overflow}!Self {
if (len > buffer_capacity) return error.Overflow;
return Self{ .len = len };
return Self{ .len = @intCast(len) };
}

/// View the internal array as a slice whose size was previously set.
Expand All @@ -67,7 +69,7 @@ pub fn BoundedArrayAligned(
/// Does not initialize added items if any.
pub fn resize(self: *Self, len: usize) error{Overflow}!void {
if (len > buffer_capacity) return error.Overflow;
self.len = len;
self.len = @intCast(len);
}

/// Copy the content of an existing slice.
Expand Down Expand Up @@ -163,7 +165,7 @@ pub fn BoundedArrayAligned(
/// This operation is O(N).
pub fn insertSlice(self: *Self, i: usize, items: []const T) error{Overflow}!void {
try self.ensureUnusedCapacity(items.len);
self.len += items.len;
self.len = @intCast(self.len + items.len);
mem.copyBackwards(T, self.slice()[i + items.len .. self.len], self.constSlice()[i .. self.len - items.len]);
@memcpy(self.slice()[i..][0..items.len], items);
}
Expand Down Expand Up @@ -193,7 +195,7 @@ pub fn BoundedArrayAligned(
for (self.constSlice()[after_range..], 0..) |item, i| {
self.slice()[after_subrange..][i] = item;
}
self.len -= len - new_items.len;
self.len = @intCast(self.len - len + new_items.len);
}
}

Expand Down Expand Up @@ -244,7 +246,7 @@ pub fn BoundedArrayAligned(
/// enough to store the new items.
pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
const old_len = self.len;
self.len += items.len;
self.len = @intCast(self.len + items.len);
@memcpy(self.slice()[old_len..][0..items.len], items);
}

Expand All @@ -260,8 +262,8 @@ pub fn BoundedArrayAligned(
/// Asserts the capacity is enough.
pub fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
const old_len = self.len;
self.len += n;
assert(self.len <= buffer_capacity);
assert(self.len + n <= buffer_capacity);
self.len = @intCast(self.len + n);
@memset(self.slice()[old_len..self.len], value);
}

Expand Down Expand Up @@ -387,6 +389,18 @@ test "BoundedArray" {
try testing.expectEqualStrings(s, a.constSlice());
}

test "BoundedArray sizeOf" {
// Just sanity check size on one CPU
if (@import("builtin").cpu.arch != .x86_64)
return;

try testing.expectEqual(@sizeOf(BoundedArray(u8, 3)), 4);

// `len` is the minimum required size to hold the maximum capacity
try testing.expectEqual(@TypeOf(@as(BoundedArray(u8, 15), undefined).len), u4);
try testing.expectEqual(@TypeOf(@as(BoundedArray(u8, 16), undefined).len), u5);
}

test "BoundedArrayAligned" {
var a = try BoundedArrayAligned(u8, 16, 4).init(0);
try a.append(0);
Expand Down