#pragma once #include "frame.hpp" #include #include #include #include #include #include namespace aethera { enum class Frame_Dimension : std::uint8_t { two_dimensional, three_dimensional }; enum class Frame_Statistic : std::uint8_t { plot_tick_queue_ms, plot_update_ms, plot_publish_ms, server_completion_ms, scene_render_ms, event_dispatch_ms, prepare_ms, paint_ms, backend_queue_ms, gpu_submission_ms, readback_stage_ms, callback_ms, backend_apply_ms, backend_plan_ms, backend_execute_ms, backend_submit_ms, gpu_fence_wait_ms, gpu_render_ms, gpu_transition_ms, gpu_copy_ms, gpu_total_ms, readback_ms, pipeline_2d_event_ms, pipeline_2d_prepare_ms, pipeline_2d_paint_ms, pipeline_2d_frame_target_ms, pipeline_2d_background_ms, pipeline_2d_cache_targets_ms, pipeline_2d_taskflow_ms, pipeline_2d_paint_coordination_ms, pipeline_2d_scene_coordination_ms, pipeline_2d_callback_ms, pipeline_2d_frame_handoff_ms, pipeline_3d_event_ms, pipeline_3d_prepare_ms, pipeline_3d_submit_graph_ms, pipeline_3d_scene_coordination_ms, pipeline_3d_prepare_queue_ms, pipeline_3d_backend_apply_ms, pipeline_3d_backend_plan_ms, pipeline_3d_backend_execute_ms, pipeline_3d_backend_commands_ms, pipeline_3d_backend_queue_ms, pipeline_3d_backend_submit_ms, pipeline_3d_submit_handoff_ms, pipeline_3d_gpu_render_ms, pipeline_3d_gpu_transition_ms, pipeline_3d_gpu_copy_ms, pipeline_3d_gpu_sync_ms, pipeline_3d_readback_ms, pipeline_3d_callback_ms, pipeline_3d_completion_handoff_ms, frame_interval_ms, count }; inline constexpr std::size_t frame_statistic_count = static_cast(Frame_Statistic::count); struct Frame_Statistics_Sample { std::array values{}; std::bitset present{}; void set(Frame_Statistic statistic, double value) noexcept; }; struct Statistic_State { std::size_t count{}; double latest{}; double minimum{}; double maximum{}; double average{}; double trimmed_average{}; double variability{}; double p50{}; double p95{}; double p99{}; bool operator==(const Statistic_State&) const = default; }; class Sliding_Statistics final { public: Sliding_Statistics(); explicit Sliding_Statistics(std::size_t capacity); [[nodiscard]] Statistic_State submit(double value); [[nodiscard]] const Statistic_State& state() const noexcept; void reset() noexcept; private: /* P² 只维护五个标记点,分位数是从 reset 起的在线估计,不保存样本。 */ class Quantile_Estimator final { public: explicit Quantile_Estimator(double probability) noexcept; void submit(double value) noexcept; [[nodiscard]] double value() const noexcept; void reset() noexcept; private: double probability_{}; std::array initial_{}; std::array heights_{}; std::array positions_{}; std::array desired_{}; std::array increments_{}; std::size_t count_{}; }; /* 预分配单调队列,O(1) 摊还维护精确滑动窗口极值。 */ class Extremum_Queue final { public: Extremum_Queue(std::size_t capacity, bool minimum); void submit(double value, std::uint64_t sequence, std::size_t window) noexcept; [[nodiscard]] double value() const noexcept; void reset() noexcept; private: struct Node { double value{}; std::uint64_t sequence{}; }; std::vector nodes_; std::size_t head_{}; std::size_t tail_{}; bool minimum_{}; }; /* 原始值和截尾值只为精确滑动均值/方差服务,构造后不再分配。 */ std::vector values_; std::vector trimmed_values_; std::size_t size_{}; std::size_t next_{}; double sum_{}; double squared_sum_{}; double trimmed_sum_{}; bool trimmed_window_initialized_{}; std::uint64_t sequence_{}; Extremum_Queue minimum_; Extremum_Queue maximum_; Quantile_Estimator p05_{0.05}; Quantile_Estimator p50_{0.50}; Quantile_Estimator p95_{0.95}; Quantile_Estimator p99_{0.99}; Statistic_State state_{}; }; struct Frame_Statistics_State { /* 可直接通过 Scene State 双缓冲发布的定长结果;不含统计器内部样本。 */ std::array values{}; Frame_Identity identity{}; std::uint64_t created_time_unix_ns{}; std::uint64_t dropped_sequences{}; bool operator==(const Frame_Statistics_State&) const = default; }; class Frame_Statistics_Accumulator final { public: explicit Frame_Statistics_Accumulator(std::size_t capacity = 600); [[nodiscard]] const Frame_Statistics_State& submit( const Render_Frame& frame, Frame_Dimension dimension); void reset() noexcept; private: std::vector values_; Frame_Statistics_State state_{}; std::chrono::steady_clock::time_point previous_completion_{}; std::uint64_t previous_sequence_{}; }; }