延迟低了很多
This commit is contained in:
@@ -70,7 +70,6 @@ void Graph_WebSocket::deliver_frame(
|
||||
}
|
||||
|
||||
void Graph_WebSocket::receive(std::string_view message) {
|
||||
const auto received_time = std::chrono::steady_clock::now();
|
||||
const auto json = nlohmann::json::parse(message, nullptr, false);
|
||||
if (json.is_discarded() || !json.is_object()) return;
|
||||
const auto kind = json.value("kind", std::string{});
|
||||
@@ -107,11 +106,7 @@ void Graph_WebSocket::receive(std::string_view message) {
|
||||
height = d->height;
|
||||
}
|
||||
Plot_Input_Event decoded;
|
||||
decoded.coalesced_event_count = std::clamp(
|
||||
input->value("coalesced_event_count", std::size_t{1}),
|
||||
std::size_t{1}, std::size_t{1'000});
|
||||
decoded.type = *type;
|
||||
decoded.received_time = received_time;
|
||||
const auto read_point = [&](std::string_view key,
|
||||
render_2d::Point_F& point,
|
||||
bool viewport_relative) {
|
||||
|
||||
+31
-34
@@ -35,27 +35,6 @@ constexpr std::uint16_t plot_stream_protocol_version{9};
|
||||
constexpr std::size_t diagnostic_window_capacity{600};
|
||||
|
||||
|
||||
struct Web_Input_Metadata {
|
||||
Plot_Input_Event input;
|
||||
std::chrono::steady_clock::time_point scene_dispatched;
|
||||
};
|
||||
struct Web_Input_Event {
|
||||
virtual ~Web_Input_Event() = default;
|
||||
[[nodiscard]] virtual const Web_Input_Metadata& web_input_metadata() const noexcept = 0;
|
||||
};
|
||||
template <typename Event_Object_Type>
|
||||
struct Observed_Input_Event final : Event_Object_Type, Web_Input_Event {
|
||||
template <typename... Arguments>
|
||||
Observed_Input_Event(Web_Input_Metadata value_metadata,
|
||||
Arguments&&... arguments)
|
||||
: Event_Object_Type(std::forward<Arguments>(arguments)...),
|
||||
metadata(std::move(value_metadata)) {}
|
||||
[[nodiscard]] const Web_Input_Metadata& web_input_metadata() const noexcept override {
|
||||
return metadata;
|
||||
}
|
||||
Web_Input_Metadata metadata;
|
||||
};
|
||||
|
||||
std::string exception_description(const std::exception_ptr& failure) {
|
||||
try {
|
||||
if (failure) std::rethrow_exception(failure);
|
||||
@@ -202,10 +181,30 @@ void append_statistic_json(nlohmann::json& output,
|
||||
}
|
||||
}
|
||||
|
||||
void append_event_statistics_json(nlohmann::json& output,
|
||||
const Event_Statistics_State& state) {
|
||||
for (const auto type : magic_enum::enum_values<Event_Type>()) {
|
||||
auto& event = output[magic_enum::enum_name(type)];
|
||||
const auto& values = state.values[static_cast<std::size_t>(type)];
|
||||
for (const auto statistic : magic_enum::enum_values<Event_Statistic>()) {
|
||||
if (statistic == Event_Statistic::count) continue;
|
||||
const auto& value = values[static_cast<std::size_t>(statistic)];
|
||||
if (value.count == 0) continue;
|
||||
event[magic_enum::enum_name(statistic)] = {
|
||||
{"count", value.count}, {"latest", value.latest},
|
||||
{"minimum", value.minimum}, {"maximum", value.maximum},
|
||||
{"average", value.average},
|
||||
{"trimmed_average", value.trimmed_average},
|
||||
{"variability", value.variability}, {"p50", value.p50},
|
||||
{"p95", value.p95}, {"p99", value.p99}};
|
||||
}
|
||||
if (event.empty()) output.erase(std::string{magic_enum::enum_name(type)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Scene_Object>
|
||||
void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input) {
|
||||
Web_Input_Metadata metadata{input, std::chrono::steady_clock::now()};
|
||||
const auto dispatch = [&](auto event) {
|
||||
scene.template submit_stream<aethera::Scene_Event_Stream_Tag>(std::move(event));
|
||||
};
|
||||
@@ -220,15 +219,14 @@ void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input) {
|
||||
case Event_Type::pointer_move:
|
||||
case Event_Type::pointer_press:
|
||||
case Event_Type::pointer_release: {
|
||||
auto event = scene.template make_event<Observed_Input_Event<Basic_Pointer_Event<Point_F>>>(
|
||||
std::move(metadata), input.type);
|
||||
auto event = scene.template make_event<Basic_Pointer_Event<Point_F>>(
|
||||
input.type);
|
||||
apply_pointer(*event);
|
||||
dispatch(std::move(event));
|
||||
break;
|
||||
}
|
||||
case Event_Type::wheel: {
|
||||
auto event = scene.template make_event<Observed_Input_Event<Basic_Wheel_Event<Point_F>>>(
|
||||
std::move(metadata));
|
||||
auto event = scene.template make_event<Basic_Wheel_Event<Point_F>>();
|
||||
apply_pointer(*event);
|
||||
event->pixel_delta_x = input.pixel_delta_x;
|
||||
event->pixel_delta_y = input.pixel_delta_y;
|
||||
@@ -239,8 +237,7 @@ void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input) {
|
||||
}
|
||||
case Event_Type::key_press:
|
||||
case Event_Type::key_release: {
|
||||
auto event = scene.template make_event<Observed_Input_Event<Key_Event>>(
|
||||
std::move(metadata), input.type);
|
||||
auto event = scene.template make_event<Key_Event>(input.type);
|
||||
event->key = input.key;
|
||||
event->native_key = input.native_key;
|
||||
event->modifiers = input.modifiers;
|
||||
@@ -249,8 +246,7 @@ void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dispatch(scene.template make_event<Observed_Input_Event<Event>>(
|
||||
std::move(metadata), input.type));
|
||||
dispatch(scene.template make_event<Event>(input.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -728,12 +724,11 @@ void Plot::render_once() {
|
||||
void Plot::submit_input(Plot_Input_Event event) {
|
||||
ensure_started();
|
||||
if (d->terminal_failure.load(std::memory_order_acquire)) return;
|
||||
if (event.received_time == std::chrono::steady_clock::time_point{})
|
||||
event.received_time = std::chrono::steady_clock::now();
|
||||
/*
|
||||
* WebSocket 线程只向 Scene 的当前事件缓冲追加一个由 Scene
|
||||
* memory_resource 分配的基类指针。Prepare 边界交换完整批次,
|
||||
* 处理结果再由反向双缓冲交给 Plot 统计;事件处理不执行 Web 回调。
|
||||
* Scene 在 Renderable 完成消费时按 Event_Type 增量统计,并随自身
|
||||
* State 双缓冲发布;Web 层只在低频 diagnostics 请求中读取结果。
|
||||
*/
|
||||
try {
|
||||
if (auto* scene_2d = std::get_if<std::unique_ptr<Scene_2D>>(&d->scene))
|
||||
@@ -767,6 +762,7 @@ nlohmann::json Plot::generate_data(const nlohmann::json& input) {
|
||||
|
||||
nlohmann::json Plot::diagnostics() const {
|
||||
nlohmann::json frame_statistics = nlohmann::json::object();
|
||||
nlohmann::json input_statistics = nlohmann::json::object();
|
||||
Frame_Identity identity{};
|
||||
std::uint64_t created_time_unix_ns{};
|
||||
std::uint64_t dropped_sequences{};
|
||||
@@ -775,6 +771,7 @@ nlohmann::json Plot::diagnostics() const {
|
||||
const auto read_statistics = [&](const auto& state) {
|
||||
const auto& statistics = state.frame_statistics;
|
||||
append_statistic_json(frame_statistics, statistics);
|
||||
append_event_statistics_json(input_statistics, state.event_statistics);
|
||||
identity = statistics.identity;
|
||||
created_time_unix_ns = statistics.created_time_unix_ns;
|
||||
dropped_sequences = statistics.dropped_sequences;
|
||||
@@ -836,7 +833,7 @@ nlohmann::json Plot::diagnostics() const {
|
||||
{"render_enabled", pacing.render_enabled},
|
||||
{"video_enabled", pacing.video_enabled}}},
|
||||
{"frame_statistics", std::move(frame_statistics)},
|
||||
{"input_statistics", nlohmann::json::object()}};
|
||||
{"input_statistics", std::move(input_statistics)}};
|
||||
if (is_3d) {
|
||||
const auto gpu = gpu_completion_state();
|
||||
const auto milliseconds = [](std::uint64_t nanoseconds) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <render_2D/scene/Render_Scene_2D.hpp>
|
||||
#include <render_3D/scene/Render_Scene_3D.hpp>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -13,7 +12,6 @@
|
||||
|
||||
namespace aethera::web {
|
||||
struct Plot_Input_Event {
|
||||
std::size_t coalesced_event_count{1}; /* 浏览器显示周期内合并的原始输入数量。 */
|
||||
Event_Type type{Event_Type::pointer_move}; /* 输入事件业务类型。 */
|
||||
render_2d::Point_F position{}; /* Plot 像素坐标。 */
|
||||
render_2d::Point_F global_position{}; /* 浏览器屏幕像素坐标。 */
|
||||
@@ -27,7 +25,6 @@ struct Plot_Input_Event {
|
||||
Key key{Key::unknown}; /* 标准化键盘按键。 */
|
||||
std::uint32_t native_key{}; /* 浏览器原生按键码。 */
|
||||
bool auto_repeat{}; /* 是否为系统重复按键。 */
|
||||
std::chrono::steady_clock::time_point received_time{}; /* WebSocket 完成解析的服务端单调时刻。 */
|
||||
};
|
||||
|
||||
struct Plot_Render_Tick {
|
||||
|
||||
Reference in New Issue
Block a user