展示优化

This commit is contained in:
2026-08-03 11:53:39 +08:00
parent 86c01e4cc5
commit 547670fef8
+146 -16
View File
@@ -3,6 +3,7 @@
#include <array>
#include <atomic>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <functional>
#include <limits>
@@ -11,6 +12,7 @@
#include <string>
#include <string_view>
#include <system_error>
#include <unordered_map>
#include <utility>
#include <vector>
#include <rigtorp/MPMCQueue.h>
@@ -367,6 +369,7 @@ struct Performance_Text_Span {
Performance_Metric_Id field_id = Performance_Metric_Id::Generic_Number;
Performance_Text_Role role = Performance_Text_Role::Value;
std::string text;
std::string field_key;
double measured_width{};
double reserved_width{};
double x_offset{};
@@ -405,6 +408,7 @@ struct Performance_Worker_State {
std::atomic<std::uint64_t> next_content_version{1};
Performance_Aggregate aggregate;
std::array<Performance_Field_Layout_State, performance_field_count> field_layout_states{};
std::unordered_map<std::string, double> field_max_value_widths;
RectF last_scroll_track_rect;
RectF last_scroll_thumb_rect;
double last_content_viewport_height{};
@@ -459,6 +463,7 @@ struct Performance_Layout_Builder {
std::vector<Performance_Line_Layout> render_lines;
std::vector<Performance_Display_Text_Run> text_runs;
std::array<Performance_Field_Layout_State, performance_field_count> field_layout_states{};
std::unordered_map<std::string, double> field_max_value_widths;
RectF panel_rect;
RectF scroll_bar_rect;
RectF scroll_thumb_rect;
@@ -1021,38 +1026,155 @@ struct Performance_Layout_Builder {
|| (contains(line, "starvation_active:1"))
|| (contains(line, "confidence:low") && contains(line, "consumer_paced"));
}
static bool whitespace(char value) {
return std::isspace(static_cast<unsigned char>(value)) != 0;
}
static std::size_t metric_unit_offset(std::string_view value) {
std::size_t index = 0;
if (index < value.size() && (value[index] == '+' || value[index] == '-'))
++index;
bool has_digit = false;
while (index < value.size()) {
char current = value[index];
if (std::isdigit(static_cast<unsigned char>(current))) {
has_digit = true;
++index;
continue;
}
if (current == '.' || current == ',') {
++index;
continue;
}
break;
}
if (!has_digit || index == value.size())
return std::string_view::npos;
char unit = value[index];
if (unit == '%' || std::isalpha(static_cast<unsigned char>(unit)))
return index;
return std::string_view::npos;
}
static std::size_t first_metric_item(std::string_view text, std::size_t begin) {
std::size_t cursor = begin;
while (cursor < text.size()) {
while (cursor < text.size() && whitespace(text[cursor]))
++cursor;
std::size_t token_end = cursor;
while (token_end < text.size() && !whitespace(text[token_end]))
++token_end;
if (text.substr(cursor, token_end - cursor).find(':') != std::string_view::npos)
return cursor;
cursor = token_end;
}
return std::string_view::npos;
}
std::vector<Performance_Text_Span> plain_line_runs(const std::string& text, Canvas& canvas) {
std::vector<Performance_Text_Span> runs;
auto append = [&](std::string value, Performance_Text_Role role, double offset) {
std::unordered_map<std::string, std::size_t> field_occurrences;
double offset = 0.0;
bool warning = warning_line(text);
double space_width = canvas.measure_text("0 0").width - canvas.measure_text("00").width;
if (space_width <= 0.0)
space_width = std::max(1.0, canvas.measure_text("0").width * 0.5);
auto trim = [](std::string_view value) {
while (!value.empty() && whitespace(value.front()))
value.remove_prefix(1);
while (!value.empty() && whitespace(value.back()))
value.remove_suffix(1);
return std::string(value);
};
auto append = [&](std::string value, Performance_Text_Role role, bool is_value = false, std::string field_key = {}) {
if (value.empty())
return;
Performance_Text_Span run;
run.text = std::move(value);
run.field_key = std::move(field_key);
run.role = role;
run.value = is_value;
run.column_index = 0;
run.x_offset = offset;
measure_run(canvas, run);
if (std::all_of(run.text.begin(), run.text.end(), whitespace)) {
run.measured_width = space_width * static_cast<double>(run.text.size());
run.reserved_width = run.measured_width;
}
offset += run_width(run);
runs.push_back(std::move(run));
};
auto make_field_key = [&](std::string_view section, std::string_view context, std::string_view label) {
std::string key;
key.reserve(section.size() + context.size() + label.size() + 3);
key.append(section);
key.push_back('|');
key.append(context);
key.push_back('|');
key.append(label);
std::size_t occurrence = field_occurrences[key]++;
key.push_back('|');
key += std::to_string(occurrence);
return key;
};
auto append_value = [&](std::string_view value, const std::string& field_key) {
Performance_Text_Role value_role = warning ? Performance_Text_Role::Warning : Performance_Text_Role::Value;
std::size_t unit_offset = metric_unit_offset(value);
if (unit_offset == std::string_view::npos) {
append(std::string(value), value_role, true, field_key);
return;
}
append(std::string(value.substr(0, unit_offset)), value_role, true, field_key);
append(std::string(value.substr(unit_offset)), warning ? Performance_Text_Role::Warning : Performance_Text_Role::Unit);
};
std::size_t cursor = 0;
std::string section;
std::size_t section_end = text.find(']');
if (!text.empty() && text.front() == '[' && section_end != std::string::npos) {
std::string section = text.substr(0, section_end + 1);
append(section, Performance_Text_Role::Section, 0.0);
double section_width = runs.empty() ? 0.0 : runs.back().measured_width + canvas.measure_text(" ").width;
Performance_Text_Role value_role = warning_line(text) ? Performance_Text_Role::Warning : Performance_Text_Role::Value;
append(text.substr(section_end + 1), value_role, section_width);
section = text.substr(0, section_end + 1);
append(section, Performance_Text_Role::Section);
cursor = section_end + 1;
}
std::size_t item_begin = first_metric_item(text, cursor);
if (item_begin == std::string_view::npos) {
append(text.substr(cursor), warning ? Performance_Text_Role::Warning : Performance_Text_Role::Value);
return runs;
}
std::size_t colon = text.find(':');
if (colon != std::string::npos) {
std::string label = text.substr(0, colon + 1);
append(label, Performance_Text_Role::Label, 0.0);
double label_width = runs.empty() ? 0.0 : runs.back().measured_width + canvas.measure_text(" ").width;
Performance_Text_Role value_role = warning_line(text) ? Performance_Text_Role::Warning : Performance_Text_Role::Value;
append(text.substr(colon + 1), value_role, label_width);
return runs;
std::string context = trim(std::string_view(text).substr(cursor, item_begin - cursor));
if (item_begin > cursor)
append(text.substr(cursor, item_begin - cursor), Performance_Text_Role::Label);
cursor = item_begin;
while (cursor < text.size()) {
std::size_t whitespace_end = cursor;
while (whitespace_end < text.size() && whitespace(text[whitespace_end]))
++whitespace_end;
if (whitespace_end > cursor)
append(text.substr(cursor, whitespace_end - cursor), Performance_Text_Role::Muted);
cursor = whitespace_end;
if (cursor >= text.size())
break;
std::size_t token_end = cursor;
while (token_end < text.size() && !whitespace(text[token_end]))
++token_end;
std::size_t colon = text.find(':', cursor);
if (colon == std::string::npos || colon >= token_end) {
std::string token = text.substr(cursor, token_end - cursor);
append(token, warning ? Performance_Text_Role::Warning : Performance_Text_Role::Label);
std::size_t next = token_end;
while (next < text.size() && whitespace(text[next]))
++next;
std::size_t next_end = next;
while (next_end < text.size() && !whitespace(text[next_end]))
++next_end;
std::size_t next_colon = text.find(':', next);
if (next < text.size() && next_colon != std::string::npos && next_colon < next_end)
context = token;
cursor = token_end;
continue;
}
std::string_view label = std::string_view(text).substr(cursor, colon - cursor);
std::string field_key = make_field_key(section, context, label);
append(text.substr(cursor, colon - cursor + 1), Performance_Text_Role::Label);
append_value(std::string_view(text).substr(colon + 1, token_end - colon - 1), field_key);
cursor = token_end;
}
append(text, Performance_Text_Role::Value, 0.0);
return runs;
}
void build_render_lines(Canvas& canvas) {
@@ -1062,7 +1184,7 @@ struct Performance_Layout_Builder {
Performance_Line_Layout line;
std::vector<Performance_Text_Span> runs = plain_line_runs(text, canvas);
for (auto& run : runs) {
line.width = std::max(line.width, run.x_offset + run.measured_width);
line.width = std::max(line.width, run.x_offset + run_width(run));
line.runs.push_back(std::move(run));
}
if (!line.runs.empty())
@@ -1223,6 +1345,12 @@ struct Performance_Layout_Builder {
run.reserved_width = run.measured_width;
return;
}
if (!run.field_key.empty()) {
double& max_width = field_max_value_widths[run.field_key];
max_width = std::max(max_width, run.measured_width);
run.reserved_width = max_width;
return;
}
auto index = static_cast<std::size_t>(run.field_id);
if (index >= field_layout_states.size())
index = static_cast<std::size_t>(Performance_Metric_Id::Generic_Number);
@@ -1390,6 +1518,7 @@ struct Performance_Overlay_Private {
Performance_Layout_Builder layout;
layout.aggregate = worker_state.aggregate;
layout.field_layout_states = worker_state.field_layout_states;
layout.field_max_value_widths = worker_state.field_max_value_widths;
layout.rebuild_lines();
auto snapshot = std::make_shared<Performance_Display_Snapshot>();
snapshot->content_version = worker_state.next_content_version.fetch_add(1, std::memory_order_acq_rel);
@@ -1429,6 +1558,7 @@ struct Performance_Overlay_Private {
layout.build_render_lines(measure_canvas);
}
worker_state.field_layout_states = layout.field_layout_states;
worker_state.field_max_value_widths = layout.field_max_value_widths;
snapshot->lines = layout.display_lines();
layout.update_content_width(&state, worker_state.maximum_content_width, viewport.width);
double line_height = std::max(1.0, metrics.line_height());