diff --git a/src/bench/vt-insert-lines.sh b/src/bench/vt-insert-lines.sh new file mode 100755 index 000000000..5c19712cc --- /dev/null +++ b/src/bench/vt-insert-lines.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# +# Uncomment to test with an active terminal state. +# ARGS=" --terminal" + +hyperfine \ + --warmup 10 \ + -n new \ + "./zig-out/bin/bench-vt-insert-lines --mode=new${ARGS}" \ + -n old \ + "./zig-out/bin/bench-vt-insert-lines --mode=old${ARGS}" + diff --git a/src/bench/vt-insert-lines.zig b/src/bench/vt-insert-lines.zig new file mode 100644 index 000000000..f7dc4064c --- /dev/null +++ b/src/bench/vt-insert-lines.zig @@ -0,0 +1,88 @@ +//! This benchmark tests the speed of the "insertLines" operation on a terminal. + +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const ArenaAllocator = std.heap.ArenaAllocator; +const cli = @import("../cli.zig"); +const terminal = @import("../terminal/main.zig"); + +const Args = struct { + mode: Mode = .old, + + /// The number of times to loop. + count: usize = 15_000, + + /// Rows and cols in the terminal. + rows: usize = 100, + cols: usize = 300, + + /// 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; + } +}; + +const Mode = enum { + /// The default allocation strategy of the structure. + old, + + /// Use a memory pool to allocate pages from a backing buffer. + new, +}; + +pub const std_options: std.Options = .{ + .log_level = .debug, +}; + +pub fn main() !void { + // We want to use the c allocator because it is much faster than GPA. + const alloc = std.heap.c_allocator; + + // Parse our args + var args: Args = .{}; + defer args.deinit(); + { + var iter = try std.process.argsWithAllocator(alloc); + defer iter.deinit(); + try cli.args.parse(Args, alloc, &args, &iter); + } + + // Handle the modes that do not depend on terminal state first. + switch (args.mode) { + .old => { + var t = try terminal.Terminal.init(alloc, args.cols, args.rows); + defer t.deinit(alloc); + try bench(&t, args); + }, + + .new => { + var t = try terminal.new.Terminal.init( + alloc, + @intCast(args.cols), + @intCast(args.rows), + ); + defer t.deinit(alloc); + try bench(&t, args); + }, + } +} + +noinline fn bench(t: anytype, args: Args) !void { + // We fill the terminal with letters. + for (0..args.rows) |row| { + for (0..args.cols) |col| { + t.setCursorPos(row + 1, col + 1); + try t.print('A'); + } + } + + for (0..args.count) |_| { + for (0..args.rows) |i| { + _ = try t.insertLines(i); + } + } +} diff --git a/src/build_config.zig b/src/build_config.zig index 742a2b692..d724cd77f 100644 --- a/src/build_config.zig +++ b/src/build_config.zig @@ -144,4 +144,5 @@ pub const ExeEntrypoint = enum { bench_codepoint_width, bench_grapheme_break, bench_page_init, + bench_vt_insert_lines, }; diff --git a/src/main.zig b/src/main.zig index 3a5357471..c66c8e226 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,4 +11,5 @@ pub usingnamespace switch (build_config.exe_entrypoint) { .bench_codepoint_width => @import("bench/codepoint-width.zig"), .bench_grapheme_break => @import("bench/grapheme-break.zig"), .bench_page_init => @import("bench/page-init.zig"), + .bench_vt_insert_lines => @import("bench/vt-insert-lines.zig"), };