性能优化循环
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user