Skip to content

Commit

Permalink
fix: separate benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
tensorush committed Jul 18, 2024
1 parent 9951c8e commit 15003b7
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 83 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ const sieve_mod = sieve_dep.module("sieve");
<compile>.root_module.addImport("sieve", sieve_mod);
```

### :bar_chart: Benchmarks

- Sequence: the time to cache and retrieve integer values.

```sh
$ zig build bench -- -s
Sequence: 28.833us
```

- Composite: the time to cache and retrieve composite values.

```sh
$ zig build bench -- -c
Composite: 45.291us
```

- Composite (normal): the time to cache and retrieve normally-distributed composite values.

```sh
$ zig build bench -- -n
Composite Normal: 135.25us
```

<!-- MARKDOWN LINKS -->

[ci-shd]: https://img.shields.io/github/actions/workflow/status/tensorush/zig-sieve/ci.yaml?branch=main&style=for-the-badge&logo=github&label=CI&labelColor=black
Expand Down
4 changes: 3 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ pub fn build(b: *std.Build) void {
});

const benchs_run = b.addRunArtifact(benchs);
if (b.args) |args| {
benchs_run.addArgs(args);
}
benchs_step.dependOn(&benchs_run.step);
b.default_step.dependOn(benchs_step);

// Test suite
const tests_step = b.step("test", "Run test suite");
Expand Down
180 changes: 98 additions & 82 deletions src/bench.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Root benchmark file that measures SIEVE eviction algorithm's performance.
//! Root file that benchmarks SIEVE cache eviction algorithm's performance.

const std = @import("std");
const sieve = @import("sieve.zig");
Expand All @@ -10,7 +10,6 @@ const CACHE_CAPACITY: u64 = 68;
const STD_DEV: f64 = MEAN / 3.0;

pub fn main() !void {
// Arena allocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer if (gpa.deinit() == .leak) {
@panic("Memory leak has occurred!");
Expand All @@ -20,101 +19,118 @@ pub fn main() !void {
const allocator = arena.allocator();
defer arena.deinit();

// Standard output
const std_out = std.io.getStdOut();
var buf_writer = std.io.bufferedWriter(std_out.writer());
const writer = buf_writer.writer();

// PRNG
var prng = std.Random.DefaultPrng.init(blk: {
var seed: u64 = undefined;
try std.posix.getrandom(std.mem.asBytes(&seed));
break :blk seed;
});
const random = prng.random();

// "Sequence" benchmark
{
const Cache = sieve.Cache(u64, u64);
var cache = try Cache.init(allocator, CACHE_CAPACITY);
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = i % 100;
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = num };
_ = try cache.put(node);
}

while (i < NUM_ITERS) : (i += 1) {
num = i % 100;
_ = cache.get(num);
}

try writer.print("Sequence: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
var buf: [1024]u8 = undefined;
var fixed_buf = std.heap.FixedBufferAllocator.init(buf[0..]);
const args = try std.process.argsAlloc(fixed_buf.allocator());

switch (args[1][1]) {
's' => try benchmarkSequence(allocator, writer),
'c' => try benchmarkComposite(allocator, random, writer),
'n' => try benchmarkCompositeNormal(allocator, random, writer),
else => @panic("Unknown benchmark!"),
}

// "Composite" benchmark
{
const Cache = sieve.Cache(u64, struct { [ARRAY_SIZE]u8, u64 });
var cache = try Cache.init(allocator, CACHE_CAPACITY);
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = random.uintLessThan(u64, 100);
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = .{ [1]u8{0} ** ARRAY_SIZE, num } };
_ = try cache.put(node);
}

while (i < NUM_ITERS) : (i += 1) {
num = random.uintLessThan(u64, 100);
_ = cache.get(num);
}

try writer.print("Composite: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
try buf_writer.flush();
}

fn benchmarkSequence(
allocator: std.mem.Allocator,
writer: anytype,
) !void {
const Cache = sieve.Cache(u64, u64);
var cache = try Cache.init(allocator, CACHE_CAPACITY);
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = i % 100;
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = num };
_ = try cache.put(node);
}

// "Composite Normal" benchmark
{
const Cache = sieve.Cache(u64, struct { [ARRAY_SIZE]u8, u64 });
var cache = try Cache.init(allocator, @intFromFloat(STD_DEV));
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = @intFromFloat(random.floatNorm(f64) * STD_DEV + MEAN);
num %= 100;
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = .{ [1]u8{0} ** ARRAY_SIZE, num } };
_ = try cache.put(node);
}

while (i < NUM_ITERS) : (i += 1) {
num = @intFromFloat(random.floatNorm(f64) * STD_DEV + MEAN);
num %= 100;
_ = cache.get(num);
}

try writer.print("Composite Normal: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
while (i < NUM_ITERS) : (i += 1) {
num = i % 100;
_ = cache.get(num);
}

try buf_writer.flush();
try writer.print("Sequence: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
}

fn benchmarkComposite(
allocator: std.mem.Allocator,
random: std.Random,
writer: anytype,
) !void {
const Cache = sieve.Cache(u64, struct { [ARRAY_SIZE]u8, u64 });
var cache = try Cache.init(allocator, CACHE_CAPACITY);
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = random.uintLessThan(u64, 100);
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = .{ [1]u8{0} ** ARRAY_SIZE, num } };
_ = try cache.put(node);
}

while (i < NUM_ITERS) : (i += 1) {
num = random.uintLessThan(u64, 100);
_ = cache.get(num);
}

try writer.print("Composite: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
}

fn benchmarkCompositeNormal(
allocator: std.mem.Allocator,
random: std.Random,
writer: anytype,
) !void {
const Cache = sieve.Cache(u64, struct { [ARRAY_SIZE]u8, u64 });
var cache = try Cache.init(allocator, @intFromFloat(STD_DEV));
defer cache.deinit(allocator);

var timer = try std.time.Timer.start();
const start = timer.lap();

var node: *Cache.Node = undefined;
var num: u64 = undefined;
var i: u64 = 1;
while (i < NUM_ITERS) : (i += 1) {
num = @intFromFloat(random.floatNorm(f64) * STD_DEV + MEAN);
num %= 100;
node = try allocator.create(Cache.Node);
node.* = .{ .key = num, .value = .{ [1]u8{0} ** ARRAY_SIZE, num } };
_ = try cache.put(node);
}

while (i < NUM_ITERS) : (i += 1) {
num = @intFromFloat(random.floatNorm(f64) * STD_DEV + MEAN);
num %= 100;
_ = cache.get(num);
}

try writer.print("Composite Normal: {}\n", .{std.fmt.fmtDuration(timer.read() - start)});
}

0 comments on commit 15003b7

Please sign in to comment.