Last active
October 31, 2024 20:12
-
-
Save raindev/3361f20607c75d9d9e67733b831b2371 to your computer and use it in GitHub Desktop.
Struct alignment in Zig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", .{}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", .{}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", .{}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ./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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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