From b5ff0442d436aad2c230ce40e898dec8584fbc3a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 9 Jul 2025 14:32:34 -0700 Subject: [PATCH] bench: remove old benchmarks we converted --- src/bench/codepoint-width.sh | 34 ------ src/bench/codepoint-width.zig | 204 ---------------------------------- src/bench/grapheme-break.sh | 33 ------ src/bench/grapheme-break.zig | 144 ------------------------ src/bench/page-init.sh | 16 --- src/bench/page-init.zig | 78 ------------- src/bench/parser.zig | 71 ------------ src/build/Config.zig | 4 - src/main.zig | 4 - 9 files changed, 588 deletions(-) delete mode 100755 src/bench/codepoint-width.sh delete mode 100644 src/bench/codepoint-width.zig delete mode 100755 src/bench/grapheme-break.sh delete mode 100644 src/bench/grapheme-break.zig delete mode 100755 src/bench/page-init.sh delete mode 100644 src/bench/page-init.zig delete mode 100644 src/bench/parser.zig diff --git a/src/bench/codepoint-width.sh b/src/bench/codepoint-width.sh deleted file mode 100755 index 43304ec2e..000000000 --- a/src/bench/codepoint-width.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# -# This is a trivial helper script to help run the codepoint-width benchmark. -# You probably want to tweak this script depending on what you're -# trying to measure. - -# Options: -# - "ascii", uniform random ASCII bytes -# - "utf8", uniform random unicode characters, encoded as utf8 -# - "rand", pure random data, will contain many invalid code sequences. -DATA="utf8" -SIZE="25000000" - -# Add additional arguments -ARGS="" - -# Generate the benchmark input ahead of time so it's not included in the time. -./zig-out/bin/bench-stream --mode=gen-$DATA | head -c $SIZE > /tmp/ghostty_bench_data -#cat ~/Downloads/JAPANESEBIBLE.txt > /tmp/ghostty_bench_data - -# Uncomment to instead use the contents of `stream.txt` as input. -# yes $(cat ./stream.txt) | head -c $SIZE > /tmp/ghostty_bench_data - -hyperfine \ - --warmup 10 \ - -n noop \ - "./zig-out/bin/bench-codepoint-width --mode=noop${ARGS} try benchNoop(reader, buf), - .wcwidth => try benchWcwidth(reader, buf), - .ziglyph => try benchZiglyph(reader, buf), - .simd => try benchSimd(reader, buf), - .table => try benchTable(reader, buf), - } -} - -noinline fn benchNoop( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - _ = d.next(c); - } - } -} - -extern "c" fn wcwidth(c: u32) c_int; - -noinline fn benchWcwidth( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp| { - const width = wcwidth(cp); - - // Write the width to the buffer to avoid it being compiled away - buf[0] = @intCast(width); - } - } - } -} - -noinline fn benchTable( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp| { - // This is the same trick we do in terminal.zig so we - // keep it here. - const width = if (cp <= 0xFF) 1 else table.get(@intCast(cp)).width; - - // Write the width to the buffer to avoid it being compiled away - buf[0] = @intCast(width); - } - } - } -} - -noinline fn benchZiglyph( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp| { - const width = ziglyph.display_width.codePointWidth(cp, .half); - - // Write the width to the buffer to avoid it being compiled away - buf[0] = @intCast(width); - } - } - } -} - -noinline fn benchSimd( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp| { - const width = simd.codepointWidth(cp); - - // Write the width to the buffer to avoid it being compiled away - buf[0] = @intCast(width); - } - } - } -} diff --git a/src/bench/grapheme-break.sh b/src/bench/grapheme-break.sh deleted file mode 100755 index 24f475caa..000000000 --- a/src/bench/grapheme-break.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# -# This is a trivial helper script to help run the grapheme-break benchmark. -# You probably want to tweak this script depending on what you're -# trying to measure. - -# Options: -# - "ascii", uniform random ASCII bytes -# - "utf8", uniform random unicode characters, encoded as utf8 -# - "rand", pure random data, will contain many invalid code sequences. -DATA="utf8" -SIZE="25000000" - -# Add additional arguments -ARGS="" - -# Generate the benchmark input ahead of time so it's not included in the time. -./zig-out/bin/bench-stream --mode=gen-$DATA | head -c $SIZE > /tmp/ghostty_bench_data -#cat ~/Downloads/JAPANESEBIBLE.txt > /tmp/ghostty_bench_data - -# Uncomment to instead use the contents of `stream.txt` as input. -# yes $(cat ./stream.txt) | head -c $SIZE > /tmp/ghostty_bench_data - -hyperfine \ - --warmup 10 \ - -n noop \ - "./zig-out/bin/bench-grapheme-break --mode=noop${ARGS} try benchNoop(reader, buf), - .ziglyph => try benchZiglyph(reader, buf), - .table => try benchTable(reader, buf), - } -} - -noinline fn benchNoop( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - _ = d.next(c); - } - } -} - -noinline fn benchTable( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - var state: unicode.GraphemeBreakState = .{}; - var cp1: u21 = 0; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp2| { - const v = unicode.graphemeBreak(cp1, @intCast(cp2), &state); - buf[0] = @intCast(@intFromBool(v)); - cp1 = cp2; - } - } - } -} - -noinline fn benchZiglyph( - reader: anytype, - buf: []u8, -) !void { - var d: UTF8Decoder = .{}; - var state: u3 = 0; - var cp1: u21 = 0; - while (true) { - const n = try reader.read(buf); - if (n == 0) break; - - // Using stream.next directly with a for loop applies a naive - // scalar approach. - for (buf[0..n]) |c| { - const cp_, const consumed = d.next(c); - assert(consumed); - if (cp_) |cp2| { - const v = ziglyph.graphemeBreak(cp1, @intCast(cp2), &state); - buf[0] = @intCast(@intFromBool(v)); - cp1 = cp2; - } - } - } -} diff --git a/src/bench/page-init.sh b/src/bench/page-init.sh deleted file mode 100755 index 54712250b..000000000 --- a/src/bench/page-init.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# -# This is a trivial helper script to help run the page init benchmark. -# You probably want to tweak this script depending on what you're -# trying to measure. - -# Uncomment to test with an active terminal state. -# ARGS=" --terminal" - -hyperfine \ - --warmup 10 \ - -n alloc \ - "./zig-out/bin/bench-page-init --mode=alloc${ARGS} try benchAlloc(args.count), - .pool => try benchPool(alloc, args.count), - } -} - -noinline fn benchAlloc(count: usize) !void { - for (0..count) |_| { - _ = try terminal_new.Page.init(terminal_new.page.std_capacity); - } -} - -noinline fn benchPool(alloc: Allocator, count: usize) !void { - var list = try terminal_new.PageList.init( - alloc, - terminal_new.page.std_capacity.cols, - terminal_new.page.std_capacity.rows, - 0, - ); - defer list.deinit(); - - for (0..count) |_| { - _ = try list.grow(); - } -} diff --git a/src/bench/parser.zig b/src/bench/parser.zig deleted file mode 100644 index 9245c06cb..000000000 --- a/src/bench/parser.zig +++ /dev/null @@ -1,71 +0,0 @@ -//! 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=" - 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 = @import("../cli.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 cli.args.argsIterator(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; - } -}; diff --git a/src/build/Config.zig b/src/build/Config.zig index a9a79fb53..88ea8d6ac 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -528,11 +528,7 @@ pub const ExeEntrypoint = enum { webgen_config, webgen_actions, webgen_commands, - bench_parser, bench_stream, - bench_codepoint_width, - bench_grapheme_break, - bench_page_init, }; /// The release channel for the build. diff --git a/src/main.zig b/src/main.zig index 121a3b7d2..25e723c92 100644 --- a/src/main.zig +++ b/src/main.zig @@ -10,11 +10,7 @@ const entrypoint = switch (build_config.exe_entrypoint) { .webgen_config => @import("build/webgen/main_config.zig"), .webgen_actions => @import("build/webgen/main_actions.zig"), .webgen_commands => @import("build/webgen/main_commands.zig"), - .bench_parser => @import("bench/parser.zig"), .bench_stream => @import("bench/stream.zig"), - .bench_codepoint_width => @import("bench/codepoint-width.zig"), - .bench_grapheme_break => @import("bench/grapheme-break.zig"), - .bench_page_init => @import("bench/page-init.zig"), }; /// The main entrypoint for the program.