mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-31 04:39:01 +00:00
benchmark: add dense style replacement workload
Add a replacement mode that keeps all but one requested style live while repeatedly adding and releasing unique styles. This isolates dense backward-shift deletion and ID reuse without triggering the all-dead bulk reset. Generate replacement styles on demand so long runs continue to exercise misses instead of cycling through the resident working set.
This commit is contained in:
@@ -18,6 +18,7 @@ opts: Options,
|
||||
page: terminal.Page,
|
||||
values: []style.Style,
|
||||
ids: []style.Id,
|
||||
cursor: u24 = 0x100000,
|
||||
|
||||
pub const Options = struct {
|
||||
/// Number of distinct styles in the working set.
|
||||
@@ -37,13 +38,29 @@ pub const Mode = enum {
|
||||
/// Rebuild a working set whose previous entries are all dead, then clear
|
||||
/// all of its references again.
|
||||
churn,
|
||||
|
||||
/// Keep the set nearly full while repeatedly adding and releasing unique
|
||||
/// styles. This exercises dense deletion without the all-dead reset.
|
||||
replace,
|
||||
};
|
||||
|
||||
fn styleFor(n: u24) style.Style {
|
||||
return .{ .fg_color = .{ .rgb = .{
|
||||
.r = @truncate(n),
|
||||
.g = @truncate(n >> 8),
|
||||
.b = @truncate(n >> 16),
|
||||
} } };
|
||||
}
|
||||
|
||||
pub fn create(alloc: Allocator, opts: Options) !*StyleSet {
|
||||
if (opts.entries == 0 or opts.entries > style.Set.max_count) {
|
||||
log.err("entries must be between 1 and {}", .{style.Set.max_count});
|
||||
return error.InvalidEntries;
|
||||
}
|
||||
if (opts.mode == .replace and opts.entries < 2) {
|
||||
log.err("replace mode requires at least 2 entries", .{});
|
||||
return error.InvalidEntries;
|
||||
}
|
||||
|
||||
const ptr = try alloc.create(StyleSet);
|
||||
errdefer alloc.destroy(ptr);
|
||||
@@ -62,20 +79,28 @@ pub fn create(alloc: Allocator, opts: Options) !*StyleSet {
|
||||
errdefer alloc.free(ids);
|
||||
|
||||
for (values, 0..) |*value, i| {
|
||||
const n: u24 = @intCast(i + 1);
|
||||
value.* = .{ .fg_color = .{ .rgb = .{
|
||||
.r = @truncate(n),
|
||||
.g = @truncate(n >> 8),
|
||||
.b = @truncate(n >> 16),
|
||||
} } };
|
||||
value.* = styleFor(@intCast(i + 1));
|
||||
}
|
||||
|
||||
for (values, ids) |value, *id| {
|
||||
id.* = try page.styles.add(page.memory, value);
|
||||
}
|
||||
|
||||
if (opts.mode == .churn) {
|
||||
for (ids) |id| page.styles.release(page.memory, id);
|
||||
switch (opts.mode) {
|
||||
.lookup, .churn => {
|
||||
for (values, ids) |value, *id| {
|
||||
id.* = try page.styles.add(page.memory, value);
|
||||
}
|
||||
if (opts.mode == .churn) {
|
||||
for (ids) |id| page.styles.release(page.memory, id);
|
||||
}
|
||||
},
|
||||
.replace => {
|
||||
// Leave one slot for the unique style added by stepReplace while
|
||||
// keeping the table dense enough to exercise deletion backshifts.
|
||||
for (
|
||||
values[0 .. values.len - 1],
|
||||
ids[0 .. ids.len - 1],
|
||||
) |value, *id| {
|
||||
id.* = try page.styles.add(page.memory, value);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
ptr.* = .{
|
||||
@@ -99,10 +124,27 @@ pub fn benchmark(self: *StyleSet) Benchmark {
|
||||
.stepFn = switch (self.opts.mode) {
|
||||
.lookup => stepLookup,
|
||||
.churn => stepChurn,
|
||||
.replace => stepReplace,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
fn stepReplace(ptr: *anyopaque) Benchmark.Error!void {
|
||||
const self: *StyleSet = @ptrCast(@alignCast(ptr));
|
||||
|
||||
for (0..self.opts.loops) |_| {
|
||||
for (self.values) |_| {
|
||||
const id = self.page.styles.add(
|
||||
self.page.memory,
|
||||
styleFor(self.cursor),
|
||||
) catch return error.BenchmarkFailed;
|
||||
std.mem.doNotOptimizeAway(id);
|
||||
self.page.styles.release(self.page.memory, id);
|
||||
self.cursor +%= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn stepLookup(ptr: *anyopaque) Benchmark.Error!void {
|
||||
const self: *StyleSet = @ptrCast(@alignCast(ptr));
|
||||
|
||||
@@ -131,7 +173,7 @@ fn stepChurn(ptr: *anyopaque) Benchmark.Error!void {
|
||||
test StyleSet {
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
inline for (.{ Mode.lookup, Mode.churn }) |mode| {
|
||||
inline for (.{ Mode.lookup, Mode.churn, Mode.replace }) |mode| {
|
||||
const impl = try StyleSet.create(alloc, .{
|
||||
.entries = 64,
|
||||
.mode = mode,
|
||||
|
||||
Reference in New Issue
Block a user