3D优化完成
This commit is contained in:
@@ -302,8 +302,8 @@ nlohmann::json datoviz_observation_json(
|
||||
{"prepare_released_after_submission",
|
||||
value.prepare_released_after_submission},
|
||||
{"timings_ms", {
|
||||
{"render_domain_queue_wait",
|
||||
milliseconds(value.render_domain_queue_wait_ns)},
|
||||
{"queue_submit_wait",
|
||||
milliseconds(value.queue_submit_wait_ns)},
|
||||
{"apply", milliseconds(value.apply_ns)},
|
||||
{"emit", milliseconds(value.emit_ns)},
|
||||
{"execute", milliseconds(value.execute_ns)},
|
||||
@@ -535,6 +535,7 @@ struct Plot::Private {
|
||||
std::unique_ptr<Scene_View> view;
|
||||
std::once_flag start_once;
|
||||
std::weak_ptr<Plot> lifetime{}; /* 仅用于 completion 后重新投递 Taskflow,避免在 Scene callback 内重入 render。 */
|
||||
std::atomic<std::shared_ptr<Plot>> frame_policy_lifetime{}; /* 任一物理帧被借用期间由策略保活整个 Plot;最后一槽归还后释放。 */
|
||||
std::atomic<std::shared_ptr<const Consumer_Map>> consumers{
|
||||
std::make_shared<const Consumer_Map>()}; /* 低频订阅修改发布不可变版本。 */
|
||||
std::atomic_uint64_t next_stream_id{1};
|
||||
@@ -550,7 +551,7 @@ struct Plot::Private {
|
||||
Scene scene; /* 析构顺序保证 Scene 先停止,再释放物理帧。 */
|
||||
moodycamel::ConcurrentQueue<Plot_Render_Tick> tick_requests{}; /* 多生产者提交、唯一短任务消费的帧请求流。 */
|
||||
std::optional<Plot_Render_Tick> deferred_tick{}; /* 仅 tick consumer 任务访问的 latest 延后请求。 */
|
||||
std::atomic_uint64_t tick_request_generation{}; /* 请求入队后推进,用于关闭 consumer 尾部唤醒竞争窗口。 */
|
||||
std::atomic_uint64_t consumer_work_generation{}; /* tick 或退休帧入队后推进,关闭 consumer 尾部唤醒竞争窗口。 */
|
||||
std::atomic_bool tick_task_scheduled{}; /* 唯一短任务准入;不占用 Worker 等待。 */
|
||||
std::atomic<Render_Admission_State> render_admission{Render_Admission_State::ready}; /* Plot 渲染准入及物理槽背压的唯一状态源。 */
|
||||
std::chrono::steady_clock::time_point clock_origin{std::chrono::steady_clock::now()};
|
||||
@@ -633,6 +634,8 @@ struct Plot::Private {
|
||||
void keep_latest_tick(const Plot_Render_Tick& tick);
|
||||
void arm_tick_consumer(std::weak_ptr<Plot> lifetime);
|
||||
void release_render_admission(std::weak_ptr<Plot> lifetime);
|
||||
void retain_frame_policy_lifetime();
|
||||
void release_frame_policy_lifetime_if_idle();
|
||||
void consume_tick(std::weak_ptr<Plot> lifetime);
|
||||
void refresh_schedule();
|
||||
void clock_tick(const Plot_Render_Tick& tick);
|
||||
@@ -772,7 +775,7 @@ void Plot::Private::submit_tick_request(Plot_Render_Tick tick) {
|
||||
with_frame_policy([&](auto& policy) {
|
||||
policy.record_request(source, issued_at);
|
||||
});
|
||||
tick_request_generation.fetch_add(1, std::memory_order_release);
|
||||
consumer_work_generation.fetch_add(1, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Plot::Private::keep_latest_tick(const Plot_Render_Tick& tick) {
|
||||
@@ -831,11 +834,31 @@ void Plot::Private::release_render_admission(std::weak_ptr<Plot> lifetime) {
|
||||
arm_tick_consumer(std::move(lifetime));
|
||||
}
|
||||
|
||||
void Plot::Private::retain_frame_policy_lifetime() {
|
||||
if (frame_policy_lifetime.load(std::memory_order_acquire)) return;
|
||||
const auto owner = lifetime.lock();
|
||||
if (!owner)
|
||||
throw std::logic_error(
|
||||
"Plot frame policy cannot retain an expired Plot");
|
||||
std::shared_ptr<Plot> empty;
|
||||
static_cast<void>(frame_policy_lifetime.compare_exchange_strong(
|
||||
empty, owner, std::memory_order_release, std::memory_order_acquire));
|
||||
}
|
||||
|
||||
void Plot::Private::release_frame_policy_lifetime_if_idle() {
|
||||
if (std::ranges::any_of(frame_slots, [](const Managed_Frame& slot) {
|
||||
return slot.state.load(std::memory_order_acquire) !=
|
||||
Frame_State::available;
|
||||
}))
|
||||
return;
|
||||
frame_policy_lifetime.store({}, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Plot::Private::consume_tick(std::weak_ptr<Plot> lifetime) {
|
||||
const auto observed_generation =
|
||||
consumer_work_generation.load(std::memory_order_acquire);
|
||||
consume_retired_frames();
|
||||
if (consume_frame_policy_events()) refresh_schedule();
|
||||
const auto observed_generation =
|
||||
tick_request_generation.load(std::memory_order_acquire);
|
||||
Plot_Render_Tick requested;
|
||||
while (tick_requests.try_dequeue(requested))
|
||||
keep_latest_tick(requested);
|
||||
@@ -847,7 +870,7 @@ void Plot::Private::consume_tick(std::weak_ptr<Plot> lifetime) {
|
||||
consume_retired_frames();
|
||||
if (consume_frame_policy_events()) refresh_schedule();
|
||||
tick_task_scheduled.store(false, std::memory_order_release);
|
||||
if (tick_request_generation.load(std::memory_order_acquire) !=
|
||||
if (consumer_work_generation.load(std::memory_order_acquire) !=
|
||||
observed_generation ||
|
||||
retired_frames.load(std::memory_order_acquire) ||
|
||||
(render_admission.load(std::memory_order_acquire) ==
|
||||
@@ -1019,6 +1042,7 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
|
||||
std::memory_order_release);
|
||||
return;
|
||||
}
|
||||
retain_frame_policy_lifetime();
|
||||
managed->presentation_time =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::duration<double, std::milli>(tick.time_milliseconds));
|
||||
@@ -1030,6 +1054,7 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
|
||||
static_cast<void>(slot.state.compare_exchange_strong(
|
||||
expected, Frame_State::available, std::memory_order_acq_rel,
|
||||
std::memory_order_acquire));
|
||||
release_frame_policy_lifetime_if_idle();
|
||||
};
|
||||
bool taskflow_trace_claimed{};
|
||||
const auto restore_taskflow_trace_claim = [this, &taskflow_trace_claimed] {
|
||||
@@ -1356,6 +1381,7 @@ void Plot::Private::retire_completed_frame(not_null<Render_Frame*> frame) {
|
||||
} while (!retired_frames.compare_exchange_weak(
|
||||
head, managed, std::memory_order_release,
|
||||
std::memory_order_relaxed));
|
||||
consumer_work_generation.fetch_add(1, std::memory_order_release);
|
||||
arm_tick_consumer(lifetime);
|
||||
}
|
||||
|
||||
@@ -1442,6 +1468,7 @@ void Plot::Private::finalize_retired_frame(not_null<Render_Frame*> frame) {
|
||||
admission, Render_Admission_State::ready,
|
||||
std::memory_order_acq_rel, std::memory_order_acquire));
|
||||
arm_tick_consumer(lifetime);
|
||||
release_frame_policy_lifetime_if_idle();
|
||||
|
||||
if (captured_trace) {
|
||||
auto owner = lifetime;
|
||||
|
||||
Reference in New Issue
Block a user