014 interpreter benchmark

✓ 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", .{});
}
input.kz