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'",
|
"Build and install test executables with 'build'",
|
||||||
) orelse false;
|
) orelse false;
|
||||||
|
|
||||||
|
// Add our benchmarks
|
||||||
|
try benchSteps(b, target, mode);
|
||||||
|
|
||||||
const exe = b.addExecutable("ghostty", "src/main.zig");
|
const exe = b.addExecutable("ghostty", "src/main.zig");
|
||||||
const exe_options = b.addOptions();
|
const exe_options = b.addOptions();
|
||||||
exe_options.addOption(bool, "tracy_enabled", tracy);
|
exe_options.addOption(bool, "tracy_enabled", tracy);
|
||||||
@ -337,6 +340,44 @@ fn addDeps(
|
|||||||
try glfw.link(b, imgui_step, glfw_opts);
|
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(
|
fn conformanceSteps(
|
||||||
b: *std.build.Builder,
|
b: *std.build.Builder,
|
||||||
target: std.zig.CrossTarget,
|
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