✓
Passing This code compiles and runs correctly.
Code
// Benchmark: Koru Interpreter Performance
// Measures parse and dispatch throughput
~import "$std/runtime"
const std = @import("std");
// Simple event for benchmarking
~pub event ping { value: []const u8 }
| pong { value: []const u8 }
~proc ping {
return .{ .pong = .{ .value = value } };
}
// Register for dispatch
~std.runtime:register(scope: "bench") {
ping
}
pub fn main() void {
const koru_parser = @import("koru_parser");
const koru_errors = @import("koru_errors");
std.debug.print("\n", .{});
std.debug.print("╔══════════════════════════════════════════════════════════════╗\n", .{});
std.debug.print("║ KORU INTERPRETER BENCHMARK ║\n", .{});
std.debug.print("╚══════════════════════════════════════════════════════════════╝\n\n", .{});
const dispatcher_fn = dispatch_bench;
const test_source = "~ping(value: \"test\")";
const ITERATIONS: u64 = 10_000;
// ========================================================================
// Benchmark 1: Dispatch only (pre-built invocation)
// ========================================================================
std.debug.print("Benchmark 1: Dispatch only ({d} iterations)\n", .{ITERATIONS});
{
// Use inline types from generated registry
const segments = [_][]const u8{"ping"};
const path = Path{
.module_qualifier = null,
.segments = &segments,
};
var args_array = [_]Arg{
.{ .name = "value", .value = "test" },
};
const inv = Invocation{
.path = path,
.args = &args_array,
};
var result: DispatchResult = undefined;
const start = std.time.nanoTimestamp();
var i: u64 = 0;
while (i < ITERATIONS) : (i += 1) {
dispatcher_fn(&inv, &result) catch {};
}
const end = std.time.nanoTimestamp();
const elapsed_ns: u64 = @intCast(end - start);
const elapsed_ms = @as(f64, @floatFromInt(elapsed_ns)) / 1_000_000.0;
const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed_ns)) / 1_000_000_000.0);
std.debug.print(" Time: {d:.2} ms\n", .{elapsed_ms});
std.debug.print(" Throughput: {d:.0} dispatches/sec\n", .{ops_per_sec});
std.debug.print(" Per dispatch: {d:.0} ns\n\n", .{@as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(ITERATIONS))});
}
// ========================================================================
// Benchmark 2: Parse only (no dispatch)
// ========================================================================
std.debug.print("Benchmark 2: Parse only ({d} iterations)\n", .{ITERATIONS});
{
const start = std.time.nanoTimestamp();
var i: u64 = 0;
while (i < ITERATIONS) : (i += 1) {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var reporter = koru_errors.ErrorReporter.init(allocator, "bench", test_source) catch continue;
defer reporter.deinit();
var parser = koru_parser.Parser.init(allocator, test_source, "bench", &[_][]const u8{}, null) catch continue;
defer parser.deinit();
_ = parser.parse() catch continue;
}
const end = std.time.nanoTimestamp();
const elapsed_ns: u64 = @intCast(end - start);
const elapsed_ms = @as(f64, @floatFromInt(elapsed_ns)) / 1_000_000.0;
const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed_ns)) / 1_000_000_000.0);
std.debug.print(" Time: {d:.2} ms\n", .{elapsed_ms});
std.debug.print(" Throughput: {d:.0} parses/sec\n", .{ops_per_sec});
std.debug.print(" Per parse: {d:.0} ns\n\n", .{@as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(ITERATIONS))});
}
// ========================================================================
// Benchmark 3: Full pipeline (parse + dispatch)
// ========================================================================
std.debug.print("Benchmark 3: Full pipeline - parse + dispatch ({d} iterations)\n", .{ITERATIONS});
{
const start = std.time.nanoTimestamp();
var i: u64 = 0;
while (i < ITERATIONS) : (i += 1) {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var reporter = koru_errors.ErrorReporter.init(allocator, "bench", test_source) catch continue;
defer reporter.deinit();
var parser = koru_parser.Parser.init(allocator, test_source, "bench", &[_][]const u8{}, null) catch continue;
defer parser.deinit();
const parse_result = parser.parse() catch continue;
for (parse_result.source_file.items) |item| {
if (item == .flow) {
const ast_inv = &item.flow.invocation;
const inv: *const Invocation = @ptrCast(ast_inv);
var result: DispatchResult = undefined;
dispatcher_fn(inv, &result) catch {};
break;
}
}
}
const end = std.time.nanoTimestamp();
const elapsed_ns: u64 = @intCast(end - start);
const elapsed_ms = @as(f64, @floatFromInt(elapsed_ns)) / 1_000_000.0;
const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed_ns)) / 1_000_000_000.0);
std.debug.print(" Time: {d:.2} ms\n", .{elapsed_ms});
std.debug.print(" Throughput: {d:.0} requests/sec\n", .{ops_per_sec});
std.debug.print(" Per request: {d:.0} ns\n\n", .{@as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(ITERATIONS))});
}
// ========================================================================
// Summary
// ========================================================================
std.debug.print("NOTE: Shape/flow checkers require full program context.\n", .{});
std.debug.print(" The dispatcher provides runtime validation via allowlist.\n\n", .{});
std.debug.print("╔══════════════════════════════════════════════════════════════╗\n", .{});
std.debug.print("║ BENCHMARK COMPLETE ║\n", .{});
std.debug.print("╚══════════════════════════════════════════════════════════════╝\n", .{});
}