mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #1477 from qwerasd205/improve-benchmarks
Benchmark improvements
This commit is contained in:
@ -4,17 +4,27 @@
|
|||||||
# You probably want to tweak this script depending on what you're
|
# You probably want to tweak this script depending on what you're
|
||||||
# trying to measure.
|
# trying to measure.
|
||||||
|
|
||||||
DATA="ascii"
|
# Options:
|
||||||
SIZE="25M"
|
# - "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"
|
||||||
|
|
||||||
# Uncomment to test with an active terminal state.
|
# Uncomment to test with an active terminal state.
|
||||||
#ARGS=" --terminal"
|
# ARGS=" --terminal"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Uncomment to instead use the contents of `stream.txt` as input.
|
||||||
|
# yes $(cat ./stream.txt) | head -c $SIZE > /tmp/ghostty_bench_data
|
||||||
|
|
||||||
hyperfine \
|
hyperfine \
|
||||||
--warmup 10 \
|
--warmup 10 \
|
||||||
-n memcpy \
|
-n memcpy \
|
||||||
"./zig-out/bin/bench-stream --mode=gen-${DATA} | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=noop${ARGS}" \
|
"./zig-out/bin/bench-stream --mode=noop${ARGS} </tmp/ghostty_bench_data" \
|
||||||
-n scalar \
|
-n scalar \
|
||||||
"./zig-out/bin/bench-stream --mode=gen-${DATA} | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=scalar${ARGS}" \
|
"./zig-out/bin/bench-stream --mode=scalar${ARGS} </tmp/ghostty_bench_data" \
|
||||||
-n simd \
|
-n simd \
|
||||||
"./zig-out/bin/bench-stream --mode=gen-${DATA} | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=simd${ARGS}"
|
"./zig-out/bin/bench-stream --mode=simd${ARGS} </tmp/ghostty_bench_data"
|
||||||
|
@ -19,6 +19,10 @@ const terminal = @import("../terminal/main.zig");
|
|||||||
const Args = struct {
|
const Args = struct {
|
||||||
mode: Mode = .noop,
|
mode: Mode = .noop,
|
||||||
|
|
||||||
|
/// The PRNG seed used by the input generators.
|
||||||
|
/// -1 uses a random seed (default)
|
||||||
|
seed: i64 = -1,
|
||||||
|
|
||||||
/// Process input with a real terminal. This will be MUCH slower than
|
/// Process input with a real terminal. This will be MUCH slower than
|
||||||
/// the other modes because it has to maintain terminal state but will
|
/// the other modes because it has to maintain terminal state but will
|
||||||
/// help get more realistic numbers.
|
/// help get more realistic numbers.
|
||||||
@ -59,10 +63,11 @@ const Mode = enum {
|
|||||||
// Generate an infinite stream of random printable ASCII characters.
|
// Generate an infinite stream of random printable ASCII characters.
|
||||||
@"gen-ascii",
|
@"gen-ascii",
|
||||||
|
|
||||||
// Generate an infinite stream of repeated UTF-8 characters. We don't
|
// Generate an infinite stream of random printable unicode characters.
|
||||||
// currently do random generation because trivial implementations are
|
|
||||||
// too slow and I'm a simple man.
|
|
||||||
@"gen-utf8",
|
@"gen-utf8",
|
||||||
|
|
||||||
|
// Generate an infinite stream of arbitrary random bytes.
|
||||||
|
@"gen-rand",
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const std_options = struct {
|
pub const std_options = struct {
|
||||||
@ -86,10 +91,14 @@ pub fn main() !void {
|
|||||||
const writer = std.io.getStdOut().writer();
|
const writer = std.io.getStdOut().writer();
|
||||||
const buf = try alloc.alloc(u8, args.@"buffer-size");
|
const buf = try alloc.alloc(u8, args.@"buffer-size");
|
||||||
|
|
||||||
|
const seed: u64 = if (args.seed >= 0) @bitCast(args.seed)
|
||||||
|
else @truncate(@as(u128, @bitCast(std.time.nanoTimestamp())));
|
||||||
|
|
||||||
// Handle the modes that do not depend on terminal state first.
|
// Handle the modes that do not depend on terminal state first.
|
||||||
switch (args.mode) {
|
switch (args.mode) {
|
||||||
.@"gen-ascii" => try genAscii(writer),
|
.@"gen-ascii" => try genAscii(writer, seed),
|
||||||
.@"gen-utf8" => try genUtf8(writer),
|
.@"gen-utf8" => try genUtf8(writer, seed),
|
||||||
|
.@"gen-rand" => try genRand(writer, seed),
|
||||||
.noop => try benchNoop(reader, buf),
|
.noop => try benchNoop(reader, buf),
|
||||||
|
|
||||||
// Handle the ones that depend on terminal state next
|
// Handle the ones that depend on terminal state next
|
||||||
@ -124,17 +133,17 @@ pub fn main() !void {
|
|||||||
|
|
||||||
/// Generates an infinite stream of random printable ASCII characters.
|
/// Generates an infinite stream of random printable ASCII characters.
|
||||||
/// This has no control characters in it at all.
|
/// This has no control characters in it at all.
|
||||||
fn genAscii(writer: anytype) !void {
|
fn genAscii(writer: anytype, seed: u64) !void {
|
||||||
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;':\\\",./<>?`~";
|
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;':\\\",./<>?`~";
|
||||||
try genData(writer, alphabet);
|
try genData(writer, alphabet, seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an infinite stream of bytes from the given alphabet.
|
/// Generates an infinite stream of bytes from the given alphabet.
|
||||||
fn genData(writer: anytype, alphabet: []const u8) !void {
|
fn genData(writer: anytype, alphabet: []const u8, seed: u64) !void {
|
||||||
var prng = std.rand.DefaultPrng.init(0x12345678);
|
var prng = std.rand.DefaultPrng.init(seed);
|
||||||
const rnd = prng.random();
|
const rnd = prng.random();
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
while (true) {
|
while (true) {
|
||||||
var buf: [1024]u8 = undefined;
|
|
||||||
for (&buf) |*c| {
|
for (&buf) |*c| {
|
||||||
const idx = rnd.uintLessThanBiased(usize, alphabet.len);
|
const idx = rnd.uintLessThanBiased(usize, alphabet.len);
|
||||||
c.* = alphabet[idx];
|
c.* = alphabet[idx];
|
||||||
@ -147,9 +156,36 @@ fn genData(writer: anytype, alphabet: []const u8) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genUtf8(writer: anytype) !void {
|
fn genUtf8(writer: anytype, seed: u64) !void {
|
||||||
|
var prng = std.rand.DefaultPrng.init(seed);
|
||||||
|
const rnd = prng.random();
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
while (true) {
|
while (true) {
|
||||||
writer.writeAll(random_utf8) catch |err| switch (err) {
|
var i: usize = 0;
|
||||||
|
while (i <= buf.len - 4) {
|
||||||
|
const cp: u18 = while(true) {
|
||||||
|
const cp = rnd.int(u18);
|
||||||
|
if (ziglyph.isPrint(cp)) break cp;
|
||||||
|
};
|
||||||
|
|
||||||
|
i += try std.unicode.utf8Encode(cp, buf[i..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeAll(buf[0..i]) catch |err| switch (err) {
|
||||||
|
error.BrokenPipe => return, // stdout closed
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn genRand(writer: anytype, seed: u64) !void {
|
||||||
|
var prng = std.rand.DefaultPrng.init(seed);
|
||||||
|
const rnd = prng.random();
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
while (true) {
|
||||||
|
rnd.bytes(&buf);
|
||||||
|
|
||||||
|
writer.writeAll(&buf) catch |err| switch (err) {
|
||||||
error.BrokenPipe => return, // stdout closed
|
error.BrokenPipe => return, // stdout closed
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
@ -208,8 +244,3 @@ const TerminalHandler = struct {
|
|||||||
try self.t.print(cp);
|
try self.t.print(cp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Offline-generated random UTF-8 bytes, because generating them at runtime
|
|
||||||
/// was too slow for our benchmarks. We should replace this if we can come
|
|
||||||
/// up with something that doesn't bottleneck our benchmark.
|
|
||||||
const random_utf8 = "⨴⭬∎⯀Ⳟ⳨⍈♍⒄⣹⇚ⱎ⯡⯴↩ⵆ⼳ⶦ⦥➍Ⲡ⽉❞⹀⢧€⣁ⶐ⸲⣷⏝⣶⫿▝⨽⬃ↁ↵⯙ⶵ╡∾⭡′⫼↼┫⮡ↅ⍞‡▱⺁⿒⽛⎭☜Ⱝ⣘✬⢟⁴⟹⪝ℌ❓␆╣┳⽑⺄✽ⳗⵍ⦵ⱍ⭑⛒ⅉ⛠➌₯ⵔⷋ❷ⱳ⣖⭐⮋ₒ⥚ⷃ╶⌈⸣❥⦿⪶₮╋⅌ⳬⴛ⥚♇╬❜⺷⡬⏠⧥┺❼⏲Ⓙ⽕╶⾉⺪⁑⎕⅕⼧⊀ⲡ⊺⪭⟾Ⅵ⍌⛄⠻⣻₮ⰹⴺ⪂∖⊹⤔⦒⽳⫄⍮↷⣌⩐⨼⯂◺⍙⭺⟂⎯ⱼ⫺∌⡉ⳅ⛲⡏⃘⺃ⴜ⾩⭦ⷭ⨟☌⍃⧪⮧ⓛ♮ⲓ∘⣝⤐⎭ⷺⰫⶔ☎⾨⾐≦␢⋔⢟ⶐ⏁⚄⦡⾞✊⾾⫿⪨⮰ⓙ⌽⭲⫬⒈⊻⸣⌳⋡ⱄⲛ⓬➼⌧⟮⹖♞ℚⷱ⭥⚣⏳⟾❠☏⦻⑽−∪ⅆ☁⿑⦣Ⱳ⺧⺊Ⓞ⫽⦀⃐⚽⎌⥰⚪⢌⛗⸋⛂⾽Ⰳ⍧⛗◁❠↺≍‸ⴣ⭰‾⡸⩛⭷ⵒ⚉❚⨳⑫∇┬⚌⨙╘ℹ⢱⏴∸⾀⌟⡄⺣⦦ⱏ⼚⿇├⌮⸿⯔₮—⥟╖◡ⶕ┧⒞⏖⏧⟀❲➚➳Ⰼ┸⬖⸓⁃⹚⫣┭↜〈☶≍☨╟⿹ⳙ⺽⸡⛞⚟⯓⥟┞⿄⃫⭒⠤ⓣ⬱⓼ⱒ⥖✜⛘⠶ⰽ⿉⾣➌⣋⚨⒯◱⢃◔ⱕ⫡⓱⅌Ⱨ⧵⯾┰ⱌ⼳♠⨽⪢⸳⠹⩡Ⓨ⡪⭞⼰⡧ⓖ⤘⽶ⴺ ⨨▅⏟⊕ⴡⴰ␌⚯⦀⫭⨔⬯⨢ⱽ⟓⥫⑤⊘⟧❐▜℅⋣⚏⇭⽁⪂ⲡ⯊⦥⭳⠾⠮℞⒡Ⰼ⦈⭅≉⋆☈▓⺑⡻▷Ⱑ⋖⬜┃ⵍ←⣢ↁ☚⟴⦡⨍⼡◝⯤❓◢⌡⏿⭲✏⎑⧊⼤⪠⋂⚜┯▤⟾⬬Ⓜ⨸⥪ⱘ⒖⋐⡈⏌∠⏁⓳Ⲟ⦽⢯┏Ⲹ⍰ⅹ⚏⍐⟍⣩␖⛂∜❆⤗⒨⓽";
|
|
||||||
|
Reference in New Issue
Block a user