mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Add a benchmark exe for testing parser throughput
This commit is contained in:
41
build.zig
41
build.zig
@ -72,6 +72,9 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
"Build and install test executables with 'build'",
|
||||
) orelse false;
|
||||
|
||||
// Add our benchmarks
|
||||
try benchSteps(b, target, mode);
|
||||
|
||||
const exe = b.addExecutable("ghostty", "src/main.zig");
|
||||
const exe_options = b.addOptions();
|
||||
exe_options.addOption(bool, "tracy_enabled", tracy);
|
||||
@ -337,6 +340,44 @@ fn addDeps(
|
||||
try glfw.link(b, imgui_step, glfw_opts);
|
||||
}
|
||||
|
||||
fn benchSteps(
|
||||
b: *std.build.Builder,
|
||||
target: std.zig.CrossTarget,
|
||||
mode: std.builtin.Mode,
|
||||
) !void {
|
||||
// Open the directory ./src/bench
|
||||
const c_dir_path = (comptime root()) ++ "/src/bench";
|
||||
var c_dir = try fs.openIterableDirAbsolute(c_dir_path, .{});
|
||||
defer c_dir.close();
|
||||
|
||||
// Go through and add each as a step
|
||||
var c_dir_it = c_dir.iterate();
|
||||
while (try c_dir_it.next()) |entry| {
|
||||
// Get the index of the last '.' so we can strip the extension.
|
||||
const index = std.mem.lastIndexOfScalar(u8, entry.name, '.') orelse continue;
|
||||
if (index == 0) continue;
|
||||
|
||||
// If it doesn't end in 'zig' then ignore
|
||||
if (!std.mem.eql(u8, entry.name[index + 1 ..], "zig")) continue;
|
||||
|
||||
// Name of the conformance app and full path to the entrypoint.
|
||||
const name = entry.name[0..index];
|
||||
const path = try fs.path.join(b.allocator, &[_][]const u8{
|
||||
c_dir_path,
|
||||
entry.name,
|
||||
});
|
||||
|
||||
// Executable builder.
|
||||
const bin_name = try std.fmt.allocPrint(b.allocator, "bench-{s}", .{name});
|
||||
const c_exe = b.addExecutable(bin_name, path);
|
||||
c_exe.setTarget(target);
|
||||
c_exe.setBuildMode(mode);
|
||||
c_exe.setMainPkgPath("./src");
|
||||
c_exe.install();
|
||||
try addDeps(b, c_exe, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn conformanceSteps(
|
||||
b: *std.build.Builder,
|
||||
target: std.zig.CrossTarget,
|
||||
|
71
src/bench/parser.zig
Normal file
71
src/bench/parser.zig
Normal file
@ -0,0 +1,71 @@
|
||||
//! This benchmark tests the throughput of the terminal escape code parser.
|
||||
//!
|
||||
//! To benchmark, this takes an input stream (which is expected to come in
|
||||
//! as fast as possible), runs it through the parser, and does nothing
|
||||
//! with the parse result. This bottlenecks and tests the throughput of the
|
||||
//! parser.
|
||||
//!
|
||||
//! Usage:
|
||||
//!
|
||||
//! "--f=<path>" - A file to read to parse. If path is "-" then stdin
|
||||
//! is read. Required.
|
||||
//!
|
||||
|
||||
const std = @import("std");
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const cli_args = @import("../cli_args.zig");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
// Just use a GPA
|
||||
const GPA = std.heap.GeneralPurposeAllocator(.{});
|
||||
var gpa = GPA{};
|
||||
defer _ = gpa.deinit();
|
||||
const alloc = gpa.allocator();
|
||||
|
||||
// Parse our args
|
||||
var args: Args = args: {
|
||||
var args: Args = .{};
|
||||
errdefer args.deinit();
|
||||
var iter = try std.process.argsWithAllocator(alloc);
|
||||
defer iter.deinit();
|
||||
try cli_args.parse(Args, alloc, &args, &iter);
|
||||
break :args args;
|
||||
};
|
||||
defer args.deinit();
|
||||
|
||||
// Read the file for our input
|
||||
const file = file: {
|
||||
if (std.mem.eql(u8, args.f, "-"))
|
||||
break :file std.io.getStdIn();
|
||||
|
||||
@panic("file reading not implemented yet");
|
||||
};
|
||||
|
||||
// Read all into memory (TODO: support buffers one day)
|
||||
const input = try file.reader().readAllAlloc(
|
||||
alloc,
|
||||
1024 * 1024 * 1024 * 1024 * 16, // 16 GB
|
||||
);
|
||||
defer alloc.free(input);
|
||||
|
||||
// Run our parser
|
||||
var p: terminal.Parser = .{};
|
||||
for (input) |c| {
|
||||
const actions = p.next(c);
|
||||
//std.log.warn("actions={any}", .{actions});
|
||||
_ = actions;
|
||||
}
|
||||
}
|
||||
|
||||
const Args = struct {
|
||||
f: []const u8 = "-",
|
||||
|
||||
/// This is set by the CLI parser for deinit.
|
||||
_arena: ?ArenaAllocator = null,
|
||||
|
||||
pub fn deinit(self: *Args) void {
|
||||
if (self._arena) |arena| arena.deinit();
|
||||
self.* = undefined;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user