mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-10 11:19:45 +00:00
inspector: clarify page compression memory
The PageList overview mixed structural state with a long list of exact byte counters, making the compression result difficult to interpret. Keep the overview focused on grid and scrollback structure, and add a dedicated compression section before scrollbar details. Present page states, uncompressed size, encoded ratio, resident estimate, and savings using readable units and scoped help text.
This commit is contained in:
@@ -4,7 +4,6 @@ const terminal = @import("../../terminal/main.zig");
|
||||
const pagepkg = @import("../../terminal/page.zig");
|
||||
const stylepkg = @import("../../terminal/style.zig");
|
||||
const widgets = @import("../widgets.zig");
|
||||
const units = @import("../units.zig");
|
||||
|
||||
const PageList = terminal.PageList;
|
||||
|
||||
@@ -37,6 +36,13 @@ pub const Inspector = struct {
|
||||
summaryTable(pages);
|
||||
}
|
||||
|
||||
if (cimgui.c.ImGui_CollapsingHeader(
|
||||
"Page Compression",
|
||||
cimgui.c.ImGuiTreeNodeFlags_DefaultOpen,
|
||||
)) {
|
||||
compressionTable(pages);
|
||||
}
|
||||
|
||||
if (cimgui.c.ImGui_CollapsingHeader(
|
||||
"Scrollbar & Regions",
|
||||
cimgui.c.ImGuiTreeNodeFlags_DefaultOpen,
|
||||
@@ -112,8 +118,6 @@ pub const Inspector = struct {
|
||||
};
|
||||
|
||||
fn summaryTable(pages: *const PageList) void {
|
||||
const memory = pages.memoryStats();
|
||||
|
||||
if (!cimgui.c.ImGui_BeginTable(
|
||||
"pagelist_summary",
|
||||
3,
|
||||
@@ -139,17 +143,6 @@ fn summaryTable(pages: *const PageList) void {
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text("%zu", pages.totalPages());
|
||||
|
||||
summaryCountRow(
|
||||
"Resident Pages",
|
||||
"Pages whose raw backing memory is currently resident.",
|
||||
memory.resident_pages,
|
||||
);
|
||||
summaryCountRow(
|
||||
"Compressed Pages",
|
||||
"Pages retained as encoded data with their raw backing memory discarded.",
|
||||
memory.compressed_pages,
|
||||
);
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Total Rows");
|
||||
@@ -158,57 +151,19 @@ fn summaryTable(pages: *const PageList) void {
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text("%zu", pages.total_rows);
|
||||
|
||||
summaryBytesRow(
|
||||
"Logical Page Bytes",
|
||||
"Bytes counted against the scrollback limit. Compression does not change this value.",
|
||||
pages.page_size,
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Raw Mapping Bytes",
|
||||
"Total initialized raw page mappings, including discarded mappings retained for restoration.",
|
||||
memory.raw_bytes,
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Resident Raw Bytes",
|
||||
"Raw page mapping bytes which have not been discarded.",
|
||||
memory.resident_raw_bytes,
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Decommitted Raw Bytes",
|
||||
"Raw page mapping bytes discarded while their virtual addresses remain reserved.",
|
||||
memory.decommitted_raw_bytes,
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Encoded Bytes",
|
||||
"Exact encoded storage retained for compressed pages.",
|
||||
memory.encoded_bytes,
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Estimated Resident Bytes",
|
||||
"Resident raw allocation backing, including unused pool-item tails, plus encoded storage. Allocator and representation overhead are excluded.",
|
||||
memory.estimatedResidentBytes(),
|
||||
);
|
||||
summaryBytesRow(
|
||||
"Estimated Savings",
|
||||
"Decommitted raw mapping bytes minus their replacement encoded storage.",
|
||||
memory.estimatedSavings(),
|
||||
);
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Max Size");
|
||||
cimgui.c.ImGui_Text("Scrollback Limit");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
widgets.helpMarker(
|
||||
\\Maximum bytes before pages must be evicated. The total
|
||||
\\used bytes may be higher due to minimum individual page
|
||||
\\sizes but the next allocation that would exceed this limit
|
||||
\\will evict pages from the front of the list to free up space.
|
||||
\\Maximum uncompressed logical page memory before the oldest
|
||||
\\history is evicted. Minimum page allocation sizes can make
|
||||
\\current usage temporarily exceed this value.
|
||||
);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%zu KiB",
|
||||
units.toKibiBytes(pages.maxSize()),
|
||||
);
|
||||
var limit_buf: [64]u8 = undefined;
|
||||
const limit = formatBytes(&limit_buf, pages.maxSize());
|
||||
cimgui.c.ImGui_TextUnformatted(limit.ptr);
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
@@ -217,46 +172,142 @@ fn summaryTable(pages: *const PageList) void {
|
||||
widgets.helpMarker("Current viewport anchoring mode.");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text("%s", @tagName(pages.viewport).ptr);
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Tracked Pins");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
widgets.helpMarker("Number of pins tracked for automatic updates.");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text("%zu", pages.countTrackedPins());
|
||||
}
|
||||
|
||||
fn summaryCountRow(
|
||||
label: [:0]const u8,
|
||||
help: [:0]const u8,
|
||||
value: usize,
|
||||
) void {
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("%s", label.ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
widgets.helpMarker(help);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text("%zu", value);
|
||||
}
|
||||
fn compressionTable(pages: *const PageList) void {
|
||||
const memory = pages.memoryStats();
|
||||
|
||||
fn summaryBytesRow(
|
||||
label: [:0]const u8,
|
||||
help: [:0]const u8,
|
||||
bytes: usize,
|
||||
) void {
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("%s", label.ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
widgets.helpMarker(help);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%zu bytes (%zu KiB)",
|
||||
bytes,
|
||||
units.toKibiBytes(bytes),
|
||||
if (!cimgui.c.ImGui_BeginTable(
|
||||
"pagelist_compression",
|
||||
3,
|
||||
cimgui.c.ImGuiTableFlags_BordersInnerV |
|
||||
cimgui.c.ImGuiTableFlags_RowBg |
|
||||
cimgui.c.ImGuiTableFlags_SizingFixedFit,
|
||||
)) return;
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
compressionTextRow(
|
||||
"Platform Support",
|
||||
"Whether this target can discard physical page memory while retaining " ++
|
||||
"its virtual address range. The scrollback-compression setting may " ++
|
||||
"still disable automatic compression on a supported platform.",
|
||||
if (terminal.compression_enabled) "supported" else "unsupported",
|
||||
);
|
||||
|
||||
var state_buf: [96]u8 = undefined;
|
||||
const state = std.fmt.bufPrintZ(
|
||||
&state_buf,
|
||||
"{d} compressed, {d} resident",
|
||||
.{ memory.compressed_pages, memory.resident_pages },
|
||||
) catch unreachable;
|
||||
compressionTextRow(
|
||||
"Page States",
|
||||
"Compressed pages retain an encoded allocation while their raw mapping " ++
|
||||
"is decommitted. Resident pages still have physical raw backing. " ++
|
||||
"Active, visible, and recently changed pages are expected to be resident.",
|
||||
state,
|
||||
);
|
||||
|
||||
var raw_buf: [64]u8 = undefined;
|
||||
compressionTextRow(
|
||||
"Uncompressed Size",
|
||||
"Total size of all raw page mappings. This is the approximate page " ++
|
||||
"backing memory required if no pages were compressed and is also " ++
|
||||
"the virtual address space retained across compression.",
|
||||
formatBytes(&raw_buf, memory.raw_bytes),
|
||||
);
|
||||
|
||||
var encoded_buf: [64]u8 = undefined;
|
||||
var compressed_raw_buf: [64]u8 = undefined;
|
||||
var storage_buf: [160]u8 = undefined;
|
||||
const storage = if (memory.decommitted_raw_bytes > 0) storage: {
|
||||
const ratio = percentage(
|
||||
memory.encoded_bytes,
|
||||
memory.decommitted_raw_bytes,
|
||||
);
|
||||
break :storage std.fmt.bufPrintZ(
|
||||
&storage_buf,
|
||||
"{s} encoded / {s} raw ({d:.1}%)",
|
||||
.{
|
||||
formatBytes(&encoded_buf, memory.encoded_bytes),
|
||||
formatBytes(
|
||||
&compressed_raw_buf,
|
||||
memory.decommitted_raw_bytes,
|
||||
),
|
||||
ratio,
|
||||
},
|
||||
) catch unreachable;
|
||||
} else "none";
|
||||
compressionTextRow(
|
||||
"Compressed Storage",
|
||||
"Encoded allocation size compared with the original raw size of only " ++
|
||||
"the compressed pages. The percentage is the compression ratio, " ++
|
||||
"so smaller is better. Raw physical pages have been discarded.",
|
||||
storage,
|
||||
);
|
||||
|
||||
var resident_buf: [64]u8 = undefined;
|
||||
compressionTextRow(
|
||||
"Estimated Resident",
|
||||
"Physical page backing estimated to remain after compression: resident " ++
|
||||
"raw allocations, including unused pool tails, plus encoded storage. " ++
|
||||
"Node and allocator metadata and unrelated terminal memory are excluded.",
|
||||
formatBytes(&resident_buf, memory.estimatedResidentBytes()),
|
||||
);
|
||||
|
||||
var savings_bytes_buf: [64]u8 = undefined;
|
||||
var savings_buf: [128]u8 = undefined;
|
||||
const savings = memory.estimatedSavings();
|
||||
const savings_text = std.fmt.bufPrintZ(
|
||||
&savings_buf,
|
||||
"{s} ({d:.1}% of raw page memory)",
|
||||
.{
|
||||
formatBytes(&savings_bytes_buf, savings),
|
||||
percentage(savings, memory.raw_bytes),
|
||||
},
|
||||
) catch unreachable;
|
||||
compressionTextRow(
|
||||
"Estimated Savings",
|
||||
"Physical page backing avoided across the complete PageList. This is " ++
|
||||
"decommitted raw memory minus replacement encoded storage and is " ++
|
||||
"not a measurement of total process RSS.",
|
||||
savings_text,
|
||||
);
|
||||
}
|
||||
|
||||
fn compressionTextRow(
|
||||
label: [:0]const u8,
|
||||
help: [:0]const u8,
|
||||
value: [:0]const u8,
|
||||
) void {
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("%s", label.ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
widgets.helpMarker(help);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_TextUnformatted(value.ptr);
|
||||
}
|
||||
|
||||
fn formatBytes(buf: []u8, bytes: usize) [:0]const u8 {
|
||||
if (bytes >= 1024 * 1024) {
|
||||
const value: f64 = @as(f64, @floatFromInt(bytes)) / (1024 * 1024);
|
||||
return std.fmt.bufPrintZ(buf, "{d:.2} MiB", .{value}) catch unreachable;
|
||||
}
|
||||
|
||||
if (bytes >= 1024) {
|
||||
const value: f64 = @as(f64, @floatFromInt(bytes)) / 1024;
|
||||
return std.fmt.bufPrintZ(buf, "{d:.1} KiB", .{value}) catch unreachable;
|
||||
}
|
||||
|
||||
return std.fmt.bufPrintZ(buf, "{d} B", .{bytes}) catch unreachable;
|
||||
}
|
||||
|
||||
fn percentage(numerator: usize, denominator: usize) f64 {
|
||||
if (denominator == 0) return 0;
|
||||
return 100 *
|
||||
@as(f64, @floatFromInt(numerator)) /
|
||||
@as(f64, @floatFromInt(denominator));
|
||||
}
|
||||
|
||||
fn scrollbarInfo(pages: *PageList) void {
|
||||
|
||||
Reference in New Issue
Block a user