Created
June 27, 2025 23:21
-
-
Save Rexicon226/e91d750f5842af43d96b2f0a526ba392 to your computer and use it in GitHub Desktop.
CRC-32C benchmark
This file contains hidden or 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 Wrapper = @import("crc32c.zig").Wrapper; | |
const iterations_per_byte = 1000; | |
const warmup_iterations = 10; | |
pub fn main() !void { | |
const allocator = std.heap.smp_allocator; | |
// Pin the process to a single core (1) | |
const cpu0001: std.os.linux.cpu_set_t = [1]usize{0b0001} ++ ([_]usize{0} ** (16 - 1)); | |
try std.os.linux.sched_setaffinity(0, &cpu0001); | |
const stdout = std.io.getStdOut().writer(); | |
const loops = try std.process.argsAlloc(allocator); | |
defer std.process.argsFree(allocator, loops); | |
var prng = std.Random.DefaultPrng.init(0); | |
const random = prng.random(); | |
const max_bytes = try std.fmt.parseInt(usize, loops[1], 10); | |
const pow_max_bytes = try std.math.powi(usize, 2, max_bytes); | |
const buffer = try allocator.alloc(u8, pow_max_bytes); | |
for (1..max_bytes) |N| { | |
const index = try std.math.powi(usize, 2, N); | |
const slice = buffer[0..index]; | |
random.bytes(slice); | |
try stdout.print("{},", .{index}); | |
inline for (.{ | |
.{ Wrapper.hash, "fast crc32c" }, | |
.{ std.hash.crc.Crc32Iscsi.hash, "stdlib crc32c" }, | |
}) |impl| { | |
const func, const name = impl; | |
_ = name; | |
clflush(u8, slice); | |
var i: u32 = 0; | |
var cycles: u64 = 0; | |
while (i < iterations_per_byte + warmup_iterations) : (i += 1) { | |
const start = rdtsc(); | |
std.mem.doNotOptimizeAway(func(slice)); | |
const end = rdtsc(); | |
if (i > warmup_iterations) cycles += (end - start); | |
} | |
const cycles_per_byte = cycles / iterations_per_byte; | |
try stdout.print("{d},", .{cycles_per_byte}); | |
} | |
try stdout.writeAll("\n"); | |
} | |
} | |
/// X86 cycle counter | |
inline fn rdtsc() usize { | |
var a: u32 = undefined; | |
var b: u32 = undefined; | |
asm volatile ("rdtscp" | |
: [a] "={edx}" (a), | |
[b] "={eax}" (b), | |
: | |
: "ecx" | |
); | |
return (@as(u64, a) << 32) | b; | |
} | |
inline fn clflush(comptime T: type, slice: []const T) void { | |
for (0..(slice.len) / @bitSizeOf(T) * 8) |chunk| { | |
const offset = slice.ptr + (chunk * @bitSizeOf(T) * 8); | |
asm volatile ("clflush %[ptr]" | |
: | |
: [ptr] "m" (offset), | |
: "memory" | |
); | |
} | |
} |
This file contains hidden or 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
import matplotlib.pyplot as plt | |
filename = "data.txt" | |
sizes = [] | |
new_cycles = [] | |
old_cycles = [] | |
with open(filename) as f: | |
for line in f: | |
if not line.strip(): | |
continue | |
parts = line.strip().split(",") | |
if len(parts) < 3: | |
continue | |
size, x, y = map(int, parts[:3]) | |
sizes.append(size) | |
new_cycles.append(x) | |
old_cycles.append(y) | |
# Plot | |
plt.figure(figsize=(10, 6)) | |
plt.plot(sizes, new_cycles, label="New", marker="o") | |
plt.plot(sizes, old_cycles, label="Old", marker="s") | |
plt.xscale("log", base=2) | |
plt.xlabel("Input size") | |
plt.ylabel("Cycles") | |
plt.grid(True, which="both", ls="--", alpha=0.5) | |
plt.legend() | |
plt.tight_layout() | |
plt.savefig("test.png") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment