Skip to content

Instantly share code, notes, and snippets.

@raindev
Last active October 31, 2024 20:12
Show Gist options
  • Save raindev/3361f20607c75d9d9e67733b831b2371 to your computer and use it in GitHub Desktop.
Save raindev/3361f20607c75d9d9e67733b831b2371 to your computer and use it in GitHub Desktop.
Struct alignment in Zig
const std = @import("std");
const math = std.math;
const AlignedStruct = struct {
a: u16,
b: u16,
c: u8,
};
pub fn main() !void {
std.debug.print("Size of AlignedStruct: {}\n", .{@sizeOf(AlignedStruct)});
std.debug.print("Bit size of AlignedStruct: {}\n", .{@bitSizeOf(AlignedStruct)});
std.debug.print("Alignment of AlignedStruct: {}\n", .{@alignOf(AlignedStruct)});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const count = 100_000_000;
var items: []AlignedStruct = try allocator.alloc(AlignedStruct, count);
for (0..count) |i| {
items[i] = .{
.a = @intCast(i % math.maxInt(u16)),
.b = @intCast(i % math.maxInt(u16)),
.c = @intCast(i % math.maxInt(u8)),
};
}
var even_a: usize = 0;
for (items) |*item| {
if (item.a % 2 == 0) even_a += 1;
}
if (even_a % 2 == 0) std.debug.print("very even\n", .{});
}
const std = @import("std");
const math = std.math;
const ExternStruct = extern struct {
a: u16,
b: u16,
c: u8,
};
pub fn main() !void {
std.debug.print("Size of ExternStruct: {}\n", .{@sizeOf(ExternStruct)});
std.debug.print("Bit size of ExternStruct: {}\n", .{@bitSizeOf(ExternStruct)});
std.debug.print("Alignment of ExternStruct: {}\n", .{@alignOf(ExternStruct)});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const count = 100_000_000;
var items: []ExternStruct = try allocator.alloc(ExternStruct, count);
for (0..count) |i| {
items[i] = .{
.a = @intCast(i % math.maxInt(u16)),
.b = @intCast(i % math.maxInt(u16)),
.c = @intCast(i % math.maxInt(u8)),
};
}
var even_a: usize = 0;
for (items) |*item| {
if (item.a % 2 == 0) even_a += 1;
}
if (even_a % 2 == 0) std.debug.print("very even\n", .{});
}
const std = @import("std");
const math = std.math;
const ExternStruct = extern struct {
a: u16 align(1),
b: u16 align(1),
c: u8,
};
pub fn main() !void {
std.debug.print("Size of ExternStruct: {}\n", .{@sizeOf(ExternStruct)});
std.debug.print("Bit size of ExternStruct: {}\n", .{@bitSizeOf(ExternStruct)});
std.debug.print("Alignment of ExternStruct: {}\n", .{@alignOf(ExternStruct)});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const count = 100_000_000;
var items: []ExternStruct = try allocator.alloc(ExternStruct, count);
for (0..count) |i| {
items[i] = .{
.a = @intCast(i % math.maxInt(u16)),
.b = @intCast(i % math.maxInt(u16)),
.c = @intCast(i % math.maxInt(u8)),
};
}
var even_a: usize = 0;
for (items) |*item| {
if (item.a % 2 == 0) even_a += 1;
}
if (even_a % 2 == 0) std.debug.print("very even\n", .{});
}
$ ./aligned-bench
Size of AlignedStruct: 6
Bit size of AlignedStruct: 48
Alignment of AlignedStruct: 2
$ ./packed-bench
Size of PackedStruct: 8
Bit size of PackedStruct: 40
Alignment of PackedStruct: 8
$ ./extern-bench
Size of ExternStruct: 6
Bit size of ExternStruct: 48
Alignment of ExternStruct: 2
$ ./extern-byte-bench
Size of ExternStruct: 5
Bit size of ExternStruct: 40
Alignment of ExternStruct: 1
$ hyperfine --warmup 1 ./packed-bench ./aligned-bench ./extern-bench ./extern-byte-bench
Benchmark 1: ./packed-bench
Time (mean ± σ): 1.097 s ± 0.126 s [User: 0.491 s, System: 0.587 s]
Range (min … max): 0.935 s … 1.349 s 10 runs
Benchmark 2: ./aligned-bench
Time (mean ± σ): 840.6 ms ± 63.4 ms [User: 420.5 ms, System: 406.8 ms]
Range (min … max): 765.8 ms … 983.9 ms 10 runs
Benchmark 3: ./extern-bench
Time (mean ± σ): 794.3 ms ± 14.1 ms [User: 393.7 ms, System: 394.9 ms]
Range (min … max): 773.1 ms … 810.6 ms 10 runs
Benchmark 4: ./extern-byte-bench
Time (mean ± σ): 758.7 ms ± 61.2 ms [User: 391.3 ms, System: 359.8 ms]
Range (min … max): 689.8 ms … 855.8 ms 10 runs
Summary
./extern-byte-bench ran
1.05 ± 0.09 times faster than ./extern-bench
1.11 ± 0.12 times faster than ./aligned-bench
1.45 ± 0.20 times faster than ./packed-bench
const std = @import("std");
const math = std.math;
const PackedStruct = packed struct {
a: u16,
b: u16,
c: u8,
};
pub fn main() !void {
std.debug.print("Size of PackedStruct: {}\n", .{@sizeOf(PackedStruct)});
std.debug.print("Bit size of PackedStruct: {}\n", .{@bitSizeOf(PackedStruct)});
std.debug.print("Alignment of PackedStruct: {}\n", .{@alignOf(PackedStruct)});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const count = 100_000_000;
var items: []PackedStruct = try allocator.alloc(PackedStruct, count);
for (0..count) |i| {
items[i] = .{
.a = @intCast(i % math.maxInt(u16)),
.b = @intCast(i % math.maxInt(u16)),
.c = @intCast(i % math.maxInt(u8)),
};
}
var even_a: usize = 0;
for (items) |*item| {
if (item.a % 2 == 0) even_a += 1;
}
if (even_a % 2 == 0) std.debug.print("very even\n", .{});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment