优化了 还是卡

This commit is contained in:
2026-08-25 15:03:33 +08:00
parent 2c3105cc07
commit fa93927d81
23 changed files with 1517 additions and 619 deletions
+59 -42
View File
@@ -203,6 +203,10 @@ void append_event_statistics_json(nlohmann::json& output,
}
nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
nlohmann::json markers = nlohmann::json::object();
for (const auto& marker : trace.markers)
markers[magic_enum::enum_name(marker.marker)] =
static_cast<double>(marker.elapsed_ns) / 1'000'000.0;
nlohmann::json graphs = nlohmann::json::array();
std::unordered_map<std::uint64_t, std::string> node_ids;
for (const auto& graph : trace.graphs) {
@@ -215,11 +219,15 @@ nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
nlohmann::json successors = nlohmann::json::array();
for (const auto native_id : node.successors)
successors.push_back(std::to_string(native_id));
nlohmann::json attributes = nlohmann::json::object();
for (const auto& [key, value] : node.attributes)
attributes[key] = value;
nodes.push_back({
{"native_id", std::to_string(node.native_id)}, {"id", node.node_id},
{"parent_id", node.parent_node_id}, {"name", node.name},
{"type", node.type}, {"predecessors", std::move(predecessors)},
{"successors", std::move(successors)}});
{"successors", std::move(successors)},
{"attributes", std::move(attributes)}});
}
graphs.push_back({
{"stage", graph.stage}, {"name", graph.taskflow_name},
@@ -236,9 +244,15 @@ nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
{"worker_id", task.worker_id},
{"worker_queue_size", task.worker_queue_size},
{"worker_queue_capacity", task.worker_queue_capacity},
{"ready_ms", task.ready_ms}, {"started_ms", task.started_ms},
{"finished_ms", task.finished_ms},
{"ready_ms", task.ready_ms}, {"entered_ms", task.entered_ms},
{"started_ms", task.started_ms}, {"finished_ms", task.finished_ms},
{"completed_ms", task.completed_ms},
{"duration_ms", task.duration_ms},
{"cpu_duration_ms", task.cpu_duration_ms},
{"observer_entry_ms", task.observer_entry_ms},
{"observer_exit_ms", task.observer_exit_ms},
{"observer_entry_cpu_ms", task.observer_entry_cpu_ms},
{"observer_exit_cpu_ms", task.observer_exit_cpu_ms},
{"queue_wait_ms", task.queue_wait_ms}});
}
return {
@@ -246,6 +260,7 @@ nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
{"correlation_id", trace.identity.correlation_id},
{"created_time_unix_ns", trace.created_time_unix_ns},
{"worker_count", trace.worker_count},
{"markers", std::move(markers)},
{"graphs", std::move(graphs)},
{"executions", std::move(executions)}};
}
@@ -344,7 +359,6 @@ struct Plot::Private {
mutable std::mutex tick_mutex;
std::optional<Plot_Render_Tick> pending_tick{}; /* 时钟拥塞时只保留尚未处理的最新时间点。 */
bool tick_task_scheduled{}; /* Taskflow 中是否已有唯一 tick 消费任务。 */
std::mutex render_preparation_mutex{}; /* 仅串行本图 CPU prepareScene 管理帧在途。 */
double last_clock_render_time_ms{-std::numeric_limits<double>::infinity()};
std::chrono::steady_clock::time_point clock_origin{std::chrono::steady_clock::now()};
std::atomic_uint64_t received_tick_count{}; /* 页面时钟交付给本 Plot 的 tick 总数。 */
@@ -506,24 +520,56 @@ bool Plot::Private::mark_taskflow_trace(Render_Frame& frame) {
}
void Plot::Private::render_frame(Plot_Render_Tick tick) {
std::unique_lock preparation_lock(render_preparation_mutex, std::try_to_lock);
if (!preparation_lock.owns_lock()) {
preparation_busy_count.fetch_add(1, std::memory_order_relaxed);
return;
}
if (terminal_failure.load(std::memory_order_acquire)) return;
const auto streams = stream_snapshot();
const auto pacing = frame_policy.snapshot();
if (!pacing.render_enabled || streams.consumers.empty()) return;
std::size_t slot_index{};
Managed_Frame* managed{};
{
std::lock_guard lock(frame_mutex);
if (std::ranges::none_of(frame_slots, [](const Managed_Frame& slot) {
return slot.state == Frame_State::available;
/*
* Frame_State 是 Plot 数据准备生命周期的唯一权威来源。必须在修改
* Scene/Visual 输入之前取得准入;Scene::render() 内部再拒绝已经太晚,
* 因为上一帧的异步 prepare 可能正在读取同一份业务数据。
*/
if (std::ranges::any_of(frame_slots, [](const Managed_Frame& slot) {
return slot.state == Frame_State::in_flight;
})) {
preparation_busy_count.fetch_add(1, std::memory_order_relaxed);
return;
}
const auto available = std::ranges::find_if(
frame_slots, [](const Managed_Frame& slot) {
return slot.state == Frame_State::available;
});
if (available == frame_slots.end()) {
frame_slot_busy_count.fetch_add(1, std::memory_order_relaxed);
return;
}
slot_index = static_cast<std::size_t>(
std::distance(frame_slots.begin(), available));
managed = &*available;
managed->state = Frame_State::in_flight;
managed->presentation_time =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::duration<double, std::milli>(
tick.time_milliseconds));
}
const auto rollback_unsubmitted = [this, slot_index] {
std::lock_guard lock(frame_mutex);
auto& slot = frame_slots[slot_index];
if (slot.state == Frame_State::in_flight)
slot.state = Frame_State::available;
};
bool taskflow_trace_claimed{};
const auto restore_taskflow_trace_claim = [this, &taskflow_trace_claimed] {
if (!std::exchange(taskflow_trace_claimed, false)) return;
taskflow_trace_remaining.fetch_add(1, std::memory_order_release);
};
try {
tick.width = streams.width;
tick.height = streams.height;
/*
@@ -550,37 +596,6 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
const std::uint64_t sequence = next_frame_sequence++;
const Frame_Identity identity{sequence, tick.sequence == 0 ? sequence : tick.sequence};
std::size_t slot_index{};
Managed_Frame* managed{};
{
std::lock_guard lock(frame_mutex);
const auto available = std::ranges::find_if(
frame_slots, [](const Managed_Frame& slot) {
return slot.state == Frame_State::available;
});
if (available == frame_slots.end()) return;
slot_index = static_cast<std::size_t>(
std::distance(frame_slots.begin(), available));
managed = &*available;
managed->state = Frame_State::in_flight;
managed->presentation_time =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::duration<double, std::milli>(
tick.time_milliseconds));
}
const auto rollback_unsubmitted = [this, slot_index] {
std::lock_guard lock(frame_mutex);
auto& slot = frame_slots[slot_index];
if (slot.state == Frame_State::in_flight)
slot.state = Frame_State::available;
};
bool taskflow_trace_claimed{};
const auto restore_taskflow_trace_claim = [this, &taskflow_trace_claimed] {
if (!std::exchange(taskflow_trace_claimed, false)) return;
taskflow_trace_remaining.fetch_add(1, std::memory_order_release);
};
try {
if (auto* scene_2d = std::get_if<std::unique_ptr<Scene_2D>>(&scene)) {
auto& output = *std::get<std::unique_ptr<Frame_2D>>(managed->frame);
output.begin(identity, pacing.video_enabled
@@ -1007,6 +1022,8 @@ nlohmann::json Plot::diagnostics() const {
{"abandoned_count", gpu.abandoned_count},
{"stopping", gpu.stopping}};
}
if (const auto failure = d->terminal_failure.load(std::memory_order_acquire))
output["terminal_failure"] = *failure;
return output;
}