Compiled temapltes.
Benchmark cleanup
This commit is contained in:
172
src/benchmarks/bench.zig
Normal file
172
src/benchmarks/bench.zig
Normal file
@@ -0,0 +1,172 @@
|
||||
//! Pugz Benchmark - Compiled Templates vs Pug.js
|
||||
//!
|
||||
//! Both Pugz and Pug.js benchmarks read from the same files:
|
||||
//! src/benchmarks/templates/*.pug (templates)
|
||||
//! src/benchmarks/templates/*.json (data)
|
||||
//!
|
||||
//! Run Pugz: zig build bench-all-compiled
|
||||
//! Run Pug.js: cd src/benchmarks/pugjs && npm install && npm run bench
|
||||
|
||||
const std = @import("std");
|
||||
const tpls = @import("tpls");
|
||||
|
||||
const iterations: usize = 2000;
|
||||
const templates_dir = "src/benchmarks/templates";
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// Data structures matching JSON files
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const SubFriend = struct {
|
||||
id: i64,
|
||||
name: []const u8,
|
||||
};
|
||||
|
||||
const Friend = struct {
|
||||
name: []const u8,
|
||||
balance: []const u8,
|
||||
age: i64,
|
||||
address: []const u8,
|
||||
picture: []const u8,
|
||||
company: []const u8,
|
||||
email: []const u8,
|
||||
emailHref: []const u8,
|
||||
about: []const u8,
|
||||
tags: []const []const u8,
|
||||
friends: []const SubFriend,
|
||||
};
|
||||
|
||||
const Account = struct {
|
||||
balance: i64,
|
||||
balanceFormatted: []const u8,
|
||||
status: []const u8,
|
||||
negative: bool,
|
||||
};
|
||||
|
||||
const Project = struct {
|
||||
name: []const u8,
|
||||
url: []const u8,
|
||||
description: []const u8,
|
||||
};
|
||||
|
||||
const SearchRecord = struct {
|
||||
imgUrl: []const u8,
|
||||
viewItemUrl: []const u8,
|
||||
title: []const u8,
|
||||
description: []const u8,
|
||||
featured: bool,
|
||||
sizes: ?[]const []const u8,
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// Main
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
std.debug.print("\n", .{});
|
||||
std.debug.print("╔═══════════════════════════════════════════════════════════════╗\n", .{});
|
||||
std.debug.print("║ Compiled Zig Templates Benchmark ({d} iterations) ║\n", .{iterations});
|
||||
std.debug.print("║ Templates: {s}/*.pug ║\n", .{templates_dir});
|
||||
std.debug.print("╚═══════════════════════════════════════════════════════════════╝\n", .{});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Load JSON data
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
std.debug.print("\nLoading JSON data...\n", .{});
|
||||
|
||||
var data_arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer data_arena.deinit();
|
||||
const data_alloc = data_arena.allocator();
|
||||
|
||||
// Load all JSON files
|
||||
const simple0 = try loadJson(struct { name: []const u8 }, data_alloc, "simple-0.json");
|
||||
const simple1 = try loadJson(struct {
|
||||
name: []const u8,
|
||||
messageCount: i64,
|
||||
colors: []const []const u8,
|
||||
primary: bool,
|
||||
}, data_alloc, "simple-1.json");
|
||||
const simple2 = try loadJson(struct {
|
||||
header: []const u8,
|
||||
header2: []const u8,
|
||||
header3: []const u8,
|
||||
header4: []const u8,
|
||||
header5: []const u8,
|
||||
header6: []const u8,
|
||||
list: []const []const u8,
|
||||
}, data_alloc, "simple-2.json");
|
||||
const if_expr = try loadJson(struct { accounts: []const Account }, data_alloc, "if-expression.json");
|
||||
const projects = try loadJson(struct {
|
||||
title: []const u8,
|
||||
text: []const u8,
|
||||
projects: []const Project,
|
||||
}, data_alloc, "projects-escaped.json");
|
||||
const search = try loadJson(struct { searchRecords: []const SearchRecord }, data_alloc, "search-results.json");
|
||||
const friends_data = try loadJson(struct { friends: []const Friend }, data_alloc, "friends.json");
|
||||
|
||||
std.debug.print("Loaded. Starting benchmark...\n\n", .{});
|
||||
|
||||
var total: f64 = 0;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Benchmark each template
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// simple-0
|
||||
total += try bench("simple-0", allocator, tpls.simple_0, simple0);
|
||||
|
||||
// simple-1
|
||||
total += try bench("simple-1", allocator, tpls.simple_1, simple1);
|
||||
|
||||
// simple-2
|
||||
total += try bench("simple-2", allocator, tpls.simple_2, simple2);
|
||||
|
||||
// if-expression
|
||||
total += try bench("if-expression", allocator, tpls.if_expression, if_expr);
|
||||
|
||||
// projects-escaped
|
||||
total += try bench("projects-escaped", allocator, tpls.projects_escaped, projects);
|
||||
|
||||
// search-results
|
||||
total += try bench("search-results", allocator, tpls.search_results, search);
|
||||
|
||||
// friends
|
||||
total += try bench("friends", allocator, tpls.friends, friends_data);
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Summary
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
std.debug.print("\n", .{});
|
||||
std.debug.print(" {s:<20} => {d:>7.1}ms\n", .{ "TOTAL", total });
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
fn loadJson(comptime T: type, alloc: std.mem.Allocator, comptime filename: []const u8) !T {
|
||||
const path = templates_dir ++ "/" ++ filename;
|
||||
const content = try std.fs.cwd().readFileAlloc(alloc, path, 10 * 1024 * 1024);
|
||||
const parsed = try std.json.parseFromSlice(T, alloc, content, .{});
|
||||
return parsed.value;
|
||||
}
|
||||
|
||||
fn bench(
|
||||
name: []const u8,
|
||||
allocator: std.mem.Allocator,
|
||||
comptime render_fn: anytype,
|
||||
data: anytype,
|
||||
) !f64 {
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
var timer = try std.time.Timer.start();
|
||||
for (0..iterations) |_| {
|
||||
_ = arena.reset(.retain_capacity);
|
||||
_ = try render_fn(arena.allocator(), data);
|
||||
}
|
||||
const ms = @as(f64, @floatFromInt(timer.read())) / 1_000_000.0;
|
||||
std.debug.print(" {s:<20} => {d:>7.1}ms\n", .{ name, ms });
|
||||
return ms;
|
||||
}
|
||||
Reference in New Issue
Block a user