follow PugJs

This commit is contained in:
2026-01-24 23:53:19 +05:30
parent 621f8def47
commit 27c4898706
893 changed files with 44597 additions and 10484 deletions

View File

@@ -1,22 +1,16 @@
//! Pugz Benchmark - Compiled Templates vs Pug.js
//! Pugz Benchmark - Template Rendering
//!
//! Both Pugz and Pug.js benchmarks read from the same files:
//! src/benchmarks/templates/*.pug (templates)
//! src/benchmarks/templates/*.json (data)
//! This benchmark uses template.zig renderWithData function.
//!
//! Run Pugz: zig build bench-all-compiled
//! Run Pug.js: cd src/benchmarks/pugjs && npm install && npm run bench
//! Run: zig build bench-v1
const std = @import("std");
const tpls = @import("tpls");
const pugz = @import("pugz");
const iterations: usize = 2000;
const templates_dir = "src/benchmarks/templates";
// ═══════════════════════════════════════════════════════════════════════════
// Data structures matching JSON files
// ═══════════════════════════════════════════════════════════════════════════
const SubFriend = struct {
id: i64,
name: []const u8,
@@ -58,10 +52,6 @@ const SearchRecord = struct {
sizes: ?[]const []const u8,
};
// ═══════════════════════════════════════════════════════════════════════════
// Main
// ═══════════════════════════════════════════════════════════════════════════
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
@@ -69,20 +59,17 @@ pub fn main() !void {
std.debug.print("\n", .{});
std.debug.print("╔═══════════════════════════════════════════════════════════════╗\n", .{});
std.debug.print("Compiled Zig Templates Benchmark ({d} iterations) ║\n", .{iterations});
std.debug.print("V1 Template 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,
@@ -108,38 +95,27 @@ pub fn main() !void {
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");
// Load template sources
const simple0_tpl = try loadTemplate(data_alloc, "simple-0.pug");
const simple1_tpl = try loadTemplate(data_alloc, "simple-1.pug");
const simple2_tpl = try loadTemplate(data_alloc, "simple-2.pug");
const if_expr_tpl = try loadTemplate(data_alloc, "if-expression.pug");
const projects_tpl = try loadTemplate(data_alloc, "projects-escaped.pug");
const search_tpl = try loadTemplate(data_alloc, "search-results.pug");
const friends_tpl = try loadTemplate(data_alloc, "friends.pug");
std.debug.print("Loaded. Starting benchmark...\n\n", .{});
var total: f64 = 0;
// ─────────────────────────────────────────────────────────────────────────
// Benchmark each template
// ─────────────────────────────────────────────────────────────────────────
total += try bench("simple-0", allocator, simple0_tpl, simple0);
total += try bench("simple-1", allocator, simple1_tpl, simple1);
total += try bench("simple-2", allocator, simple2_tpl, simple2);
total += try bench("if-expression", allocator, if_expr_tpl, if_expr);
total += try bench("projects-escaped", allocator, projects_tpl, projects);
total += try bench("search-results", allocator, search_tpl, search);
total += try bench("friends", allocator, friends_tpl, friends_data);
// 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", .{});
@@ -152,10 +128,15 @@ fn loadJson(comptime T: type, alloc: std.mem.Allocator, comptime filename: []con
return parsed.value;
}
fn loadTemplate(alloc: std.mem.Allocator, comptime filename: []const u8) ![]const u8 {
const path = templates_dir ++ "/" ++ filename;
return try std.fs.cwd().readFileAlloc(alloc, path, 1 * 1024 * 1024);
}
fn bench(
name: []const u8,
allocator: std.mem.Allocator,
comptime render_fn: anytype,
template: []const u8,
data: anytype,
) !f64 {
var arena = std.heap.ArenaAllocator.init(allocator);
@@ -164,7 +145,10 @@ fn bench(
var timer = try std.time.Timer.start();
for (0..iterations) |_| {
_ = arena.reset(.retain_capacity);
_ = try render_fn(arena.allocator(), data);
_ = pugz.template.renderWithData(arena.allocator(), template, data) catch |err| {
std.debug.print(" {s:<20} => ERROR: {}\n", .{ name, err });
return 0;
};
}
const ms = @as(f64, @floatFromInt(timer.read())) / 1_000_000.0;
std.debug.print(" {s:<20} => {d:>7.1}ms\n", .{ name, ms });