性能优化循环

This commit is contained in:
2026-07-29 18:39:39 +08:00
parent d943d82554
commit 09093a65e6
4 changed files with 71 additions and 17 deletions
+41 -11
View File
@@ -15,6 +15,8 @@ static std::uint64_t steady_now_ns() {
return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count());
}
static double elapsed_ms(std::uint64_t start_ns, std::uint64_t end_ns) {
if (end_ns <= start_ns)
return 0.0;
return static_cast<double>(end_ns - start_ns) / 1000000.0;
}
static QString job_state_text(Renderable::Job_State state) {
@@ -220,8 +222,12 @@ static double positive_frame_cost(double value) {
struct Frame_Phase_Breakdown {
double data_ms{};
double painter_ms{};
double request_wait_ms{};
double queue_ms{};
double scheduler_wait_ms{};
double present_wait_ms{};
double lock_wait_ms{};
double pipeline_ms{};
double measured_ms{};
double other_ms{};
double phase_total_ms{};
@@ -230,14 +236,20 @@ struct Frame_Phase_Breakdown {
};
static Frame_Phase_Breakdown frame_phase_breakdown(const Frame_Lifecycle_Sample& sample) {
Frame_Phase_Breakdown value;
double paint_overhead_ms = positive_frame_cost(sample.paint_event_ms - sample.paint_consume_ms - sample.paint_draw_image_ms);
double finish_overhead_ms = positive_frame_cost(sample.finish_render_ms - sample.publish_color_ms);
value.data_ms = sample.prepare_data_ms + sample.image_prepare_ms;
value.painter_ms = sample.painter_draw_ms + sample.painter_end_ms + sample.paint_draw_image_ms;
value.queue_ms = sample.request_to_submit_ms + sample.cpu_queue_wait_ms + sample.update_to_paint_ms;
value.painter_ms = sample.painter_draw_ms + sample.painter_end_ms + sample.paint_draw_image_ms + paint_overhead_ms;
value.request_wait_ms = sample.request_to_submit_ms;
value.queue_ms = sample.cpu_queue_wait_ms;
value.scheduler_wait_ms = sample.finish_queue_wait_ms;
value.present_wait_ms = sample.update_to_paint_ms;
value.lock_wait_ms = sample.color_wait_ms + sample.paint_consume_ms + sample.publish_color_ms;
value.measured_ms = value.data_ms + value.painter_ms + value.queue_ms + value.lock_wait_ms + sample.stats_log_ms;
value.pipeline_ms = sample.submit_overhead_ms + finish_overhead_ms;
value.measured_ms = value.data_ms + value.painter_ms + value.request_wait_ms + value.queue_ms + value.scheduler_wait_ms + value.present_wait_ms + value.lock_wait_ms + value.pipeline_ms + sample.stats_log_ms;
value.phase_total_ms = sample.frame_total_ms > value.measured_ms ? sample.frame_total_ms : value.measured_ms;
value.other_ms = positive_frame_cost(value.phase_total_ms - value.measured_ms);
value.necessary_ms = value.data_ms + value.painter_ms;
value.necessary_ms = value.data_ms + value.painter_ms + value.pipeline_ms + value.request_wait_ms + value.scheduler_wait_ms + value.present_wait_ms;
value.unnecessary_ms = positive_frame_cost(value.phase_total_ms - value.necessary_ms);
return value;
}
@@ -251,16 +263,24 @@ static void publish_frame_lifecycle_sample(Performance_Shower* shower, Frame_Lif
shower->set_gauge("FrameLife", "unnecessaryMs", phase.unnecessary_ms);
shower->set_gauge("FrameLife", "dataMs", phase.data_ms);
shower->set_gauge("FrameLife", "painterMs", phase.painter_ms);
shower->set_gauge("FrameLife", "requestWaitMs", phase.request_wait_ms);
shower->set_gauge("FrameLife", "queueMs", phase.queue_ms);
shower->set_gauge("FrameLife", "schedulerWaitMs", phase.scheduler_wait_ms);
shower->set_gauge("FrameLife", "presentWaitMs", phase.present_wait_ms);
shower->set_gauge("FrameLife", "lockWaitMs", phase.lock_wait_ms);
shower->set_gauge("FrameLife", "pipelineMs", phase.pipeline_ms);
shower->set_gauge("FrameLife", "otherMs", phase.other_ms);
shower->set_gauge("FrameLife", "necessaryRatio", frame_ratio_percent(phase.necessary_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "unnecessaryRatio", frame_ratio_percent(phase.unnecessary_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "otherRatio", frame_ratio_percent(phase.other_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "dataRatio", frame_ratio_percent(phase.data_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "painterRatio", frame_ratio_percent(phase.painter_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "requestWaitRatio", frame_ratio_percent(phase.request_wait_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "queueRatio", frame_ratio_percent(phase.queue_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "schedulerWaitRatio", frame_ratio_percent(phase.scheduler_wait_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "presentWaitRatio", frame_ratio_percent(phase.present_wait_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "lockWaitRatio", frame_ratio_percent(phase.lock_wait_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "pipelineRatio", frame_ratio_percent(phase.pipeline_ms, phase.phase_total_ms));
shower->set_gauge("FrameLife", "renderableCount", static_cast<double>(sample.renderable_count));
shower->set_gauge("FrameLife", "visibleRenderableCount", static_cast<double>(sample.visible_renderable_count));
}
@@ -667,7 +687,6 @@ bool Abs_Plot::submit_render_once() {
if (shower)
publish_pipeline_stats(d);
Plot_Private* private_data = d;
std::uint64_t cpu_post_ns = steady_now_ns();
auto renderable_snapshot_owner = renderive::make_shared<Renderable_Snapshot>(std::move(snapshot));
std::size_t frame_memory_hint = estimate_frame_memory(*renderable_snapshot_owner, *frame_snapshot);
Abs_Plot * plot = this;
@@ -690,13 +709,15 @@ bool Abs_Plot::submit_render_once() {
task_context->color_lease_owner = color_lease_owner;
task_context->color = color;
task_context->version = version;
task_context->cpu_post_ns = cpu_post_ns;
task_context->root = root;
task_context->renderable_snapshot_owner = renderable_snapshot_owner;
task_context->frame_snapshot = frame_snapshot;
task_context->update_states = std::move(frame_update_states);
task_context->frame_memory_hint = frame_memory_hint;
task_context->plot = plot;
std::uint64_t cpu_post_ns = steady_now_ns();
frame_lifecycle_sample.submit_overhead_ms = positive_frame_cost(elapsed_ms(submit_ns, cpu_post_ns) - frame_lifecycle_sample.prepare_data_ms - frame_lifecycle_sample.color_wait_ms);
task_context->cpu_post_ns = cpu_post_ns;
task_context->frame_lifecycle_sample = frame_lifecycle_sample;
private_data->active_render_tasks.fetch_add(1, std::memory_order_acq_rel);
scheduler.post_cpu([task_context]() {
@@ -718,9 +739,10 @@ bool Abs_Plot::submit_render_once() {
return;
}
Abs_Plot* plot = task_context->plot;
Global::instance()->render_scheduler().post([plot, private_data]() {
std::uint64_t finish_post_ns = steady_now_ns();
Global::instance()->render_scheduler().post([plot, private_data, finish_post_ns]() {
if (!private_data->destroying.load(std::memory_order_acquire))
plot->finish_render();
plot->finish_render(elapsed_ms(finish_post_ns, steady_now_ns()));
notify_render_task_done(private_data);
});
});
@@ -838,14 +860,18 @@ void Abs_Plot::mark_renderable_submitted(const std::shared_ptr<Renderable>& able
return;
able->d_ptr->next_render_submit_ns.store(now_ns + static_cast<std::uint64_t>(1000000000.0 / fps), std::memory_order_release);
}
void Abs_Plot::finish_render() {
void Abs_Plot::finish_render(double finish_queue_wait_ms) {
if (d->destroying.load(std::memory_order_acquire))
return;
std::uint64_t finish_start_ns = steady_now_ns();
Renderable::Render_Pipeline& pipeline = d->pipeline;
QRegion update_region;
auto shower_owner = performance_shower_owner(d);
Performance_Shower* shower = shower_owner.get();
Renderable::Color_Buffer* ready_color{};
Renderable::Color_Buffer* render_color = pipeline.color_by_role(Color_Render);
if (render_color)
render_color->frame_lifecycle_sample.finish_queue_wait_ms = finish_queue_wait_ms;
{
std::uint64_t publish_start_ns = steady_now_ns();
update_region = pipeline.publish_render_color();
@@ -863,6 +889,10 @@ void Abs_Plot::finish_render() {
ready_color->frame_lifecycle_sample.update_request_ns = update_request_ns;
request_update(update_region, update_request_ns);
}
else {
ready_color->frame_lifecycle_sample.update_request_ns = steady_now_ns();
}
ready_color->frame_lifecycle_sample.finish_render_ms = elapsed_ms(finish_start_ns, steady_now_ns());
on_render_request(Render_Request_Source::Finish);
}
void Abs_Plot::render_color(Renderable::Color_Buffer* color, std::uint64_t version, const std::shared_ptr<Renderable>& root, const Renderable_Snapshot& snapshot, const Plot_Render_Snapshot& render_snapshot_data, std::pmr::vector<std::shared_ptr<Update_State>>&& update_states, Frame_Lifecycle_Sample& frame_lifecycle_sample) {
@@ -971,14 +1001,14 @@ void Abs_Plot::request_update(const QRegion& region, std::uint64_t request_ns) {
if (!request_ns)
request_ns = steady_now_ns();
d->last_update_request_ns.store(request_ns, std::memory_order_release);
QTimer::singleShot(0, this, [this, region]() {
QMetaObject::invokeMethod(this, [this, region]() {
if (d->destroying.load(std::memory_order_acquire))
return;
if (region.isEmpty())
update();
else
update(region);
});
}, Qt::QueuedConnection);
}
QColor Abs_Plot::background_color() {
std::lock_guard<std::mutex> lock(render_context->mutex);
+1 -1
View File
@@ -82,7 +82,7 @@ private:
void schedule_max_fps_submit(std::uint64_t target_ns);
bool renderable_ready_for_submit(const std::shared_ptr<Renderable>& able, Render_Request_Source source, std::uint64_t now_ns);
void mark_renderable_submitted(const std::shared_ptr<Renderable>& able, std::uint64_t now_ns);
void finish_render();
void finish_render(double finish_queue_wait_ms);
void request_update(const QRegion& region, std::uint64_t request_ns = 0);
static void render_color(Renderable::Color_Buffer* color, std::uint64_t version, const std::shared_ptr<Renderable>& root, const Renderable_Snapshot& snapshot, const Plot_Render_Snapshot& render_snapshot_data, std::pmr::vector<std::shared_ptr<Update_State>>&& update_states, Frame_Lifecycle_Sample& frame_lifecycle_sample);
friend class Render_Scheduler;
+3
View File
@@ -20,13 +20,16 @@ struct Frame_Lifecycle_Sample {
double request_to_submit_ms{};
double prepare_data_ms{};
double renderable_prepare_ms{};
double submit_overhead_ms{};
double color_wait_ms{};
double cpu_queue_wait_ms{};
double finish_queue_wait_ms{};
double render_color_ms{};
double image_prepare_ms{};
double painter_draw_ms{};
double painter_end_ms{};
double publish_color_ms{};
double finish_render_ms{};
double update_to_paint_ms{};
double paint_event_ms{};
double paint_consume_ms{};
+26 -5
View File
@@ -15,8 +15,12 @@ static double ratio_percent(double value, double total) {
struct Frame_Phase_Breakdown {
double data_ms{};
double painter_ms{};
double request_wait_ms{};
double queue_ms{};
double scheduler_wait_ms{};
double present_wait_ms{};
double lock_wait_ms{};
double pipeline_ms{};
double measured_ms{};
double other_ms{};
double phase_total_ms{};
@@ -25,14 +29,20 @@ struct Frame_Phase_Breakdown {
};
static Frame_Phase_Breakdown frame_phase_breakdown(const Frame_Lifecycle_Sample& sample) {
Frame_Phase_Breakdown value;
double paint_overhead_ms = non_negative(sample.paint_event_ms - sample.paint_consume_ms - sample.paint_draw_image_ms);
double finish_overhead_ms = non_negative(sample.finish_render_ms - sample.publish_color_ms);
value.data_ms = sample.prepare_data_ms + sample.image_prepare_ms;
value.painter_ms = sample.painter_draw_ms + sample.painter_end_ms + sample.paint_draw_image_ms;
value.queue_ms = sample.request_to_submit_ms + sample.cpu_queue_wait_ms + sample.update_to_paint_ms;
value.painter_ms = sample.painter_draw_ms + sample.painter_end_ms + sample.paint_draw_image_ms + paint_overhead_ms;
value.request_wait_ms = sample.request_to_submit_ms;
value.queue_ms = sample.cpu_queue_wait_ms;
value.scheduler_wait_ms = sample.finish_queue_wait_ms;
value.present_wait_ms = sample.update_to_paint_ms;
value.lock_wait_ms = sample.color_wait_ms + sample.paint_consume_ms + sample.publish_color_ms;
value.measured_ms = value.data_ms + value.painter_ms + value.queue_ms + value.lock_wait_ms + sample.stats_log_ms;
value.pipeline_ms = sample.submit_overhead_ms + finish_overhead_ms;
value.measured_ms = value.data_ms + value.painter_ms + value.request_wait_ms + value.queue_ms + value.scheduler_wait_ms + value.present_wait_ms + value.lock_wait_ms + value.pipeline_ms + sample.stats_log_ms;
value.phase_total_ms = sample.frame_total_ms > value.measured_ms ? sample.frame_total_ms : value.measured_ms;
value.other_ms = non_negative(value.phase_total_ms - value.measured_ms);
value.necessary_ms = value.data_ms + value.painter_ms;
value.necessary_ms = value.data_ms + value.painter_ms + value.pipeline_ms + value.request_wait_ms + value.scheduler_wait_ms + value.present_wait_ms;
value.unnecessary_ms = non_negative(value.phase_total_ms - value.necessary_ms);
return value;
}
@@ -52,27 +62,38 @@ public:
<< phase.unnecessary_ms << ','
<< phase.data_ms << ','
<< phase.painter_ms << ','
<< phase.request_wait_ms << ','
<< phase.queue_ms << ','
<< phase.scheduler_wait_ms << ','
<< phase.present_wait_ms << ','
<< phase.lock_wait_ms << ','
<< phase.pipeline_ms << ','
<< phase.other_ms << ','
<< ratio_percent(phase.necessary_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.unnecessary_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.other_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.data_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.painter_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.request_wait_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.queue_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.scheduler_wait_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.present_wait_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.lock_wait_ms, phase.phase_total_ms) << ','
<< ratio_percent(phase.pipeline_ms, phase.phase_total_ms) << ','
<< ratio_percent(sample.stats_log_ms, phase.phase_total_ms) << ','
<< sample.request_to_submit_ms << ','
<< sample.prepare_data_ms << ','
<< sample.renderable_prepare_ms << ','
<< sample.submit_overhead_ms << ','
<< sample.color_wait_ms << ','
<< sample.cpu_queue_wait_ms << ','
<< sample.finish_queue_wait_ms << ','
<< sample.render_color_ms << ','
<< sample.image_prepare_ms << ','
<< sample.painter_draw_ms << ','
<< sample.painter_end_ms << ','
<< sample.publish_color_ms << ','
<< sample.finish_render_ms << ','
<< sample.update_to_paint_ms << ','
<< sample.paint_event_ms << ','
<< sample.paint_consume_ms << ','
@@ -110,7 +131,7 @@ private:
return QDir(dir).filePath("renderive_performance_log.csv");
}
std::string header() const {
return "plot_id,version,frame_total_ms,phase_total_ms,necessary_ms,unnecessary_ms,data_ms,painter_ms,queue_ms,lock_wait_ms,other_ms,necessary_ratio,unnecessary_ratio,other_ratio,data_ratio,painter_ratio,queue_ratio,lock_wait_ratio,stats_log_ratio,request_to_submit_ms,prepare_data_ms,renderable_prepare_ms,color_wait_ms,cpu_queue_wait_ms,render_color_ms,image_prepare_ms,painter_draw_ms,painter_end_ms,publish_color_ms,update_to_paint_ms,paint_event_ms,paint_consume_ms,paint_draw_image_ms,stats_log_ms,renderable_count,visible_renderable_count,direct_draw_count,local_cache_count";
return "plot_id,version,frame_total_ms,phase_total_ms,necessary_ms,unnecessary_ms,data_ms,painter_ms,request_wait_ms,queue_ms,scheduler_wait_ms,present_wait_ms,lock_wait_ms,pipeline_ms,other_ms,necessary_ratio,unnecessary_ratio,other_ratio,data_ratio,painter_ratio,request_wait_ratio,queue_ratio,scheduler_wait_ratio,present_wait_ratio,lock_wait_ratio,pipeline_ratio,stats_log_ratio,request_to_submit_ms,prepare_data_ms,renderable_prepare_ms,submit_overhead_ms,color_wait_ms,cpu_queue_wait_ms,finish_queue_wait_ms,render_color_ms,image_prepare_ms,painter_draw_ms,painter_end_ms,publish_color_ms,finish_render_ms,update_to_paint_ms,paint_event_ms,paint_consume_ms,paint_draw_image_ms,stats_log_ms,renderable_count,visible_renderable_count,direct_draw_count,local_cache_count";
}
};
Performance_Frame_Log& frame_log() {