From 87f4bbd6685fd6e2e43b05a6255ab360bd17dcf3 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 6 Feb 2022 02:29:08 +0100 Subject: [Debugger] Move most profilers to ServersDebugger. Also splits bandwidth/rpc profiler (RPCProfiler is now in SceneDebugger). --- scene/debugger/scene_debugger.cpp | 103 +++++++++++++++++++++++++++++++++++--- scene/debugger/scene_debugger.h | 28 +++++++++++ 2 files changed, 125 insertions(+), 6 deletions(-) (limited to 'scene/debugger') diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 41340f281b..e5b81f9d8d 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -31,30 +31,121 @@ #include "scene_debugger.h" #include "core/debugger/engine_debugger.h" +#include "core/debugger/engine_profiler.h" #include "core/io/marshalls.h" #include "core/object/script_language.h" #include "scene/main/scene_tree.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" -void SceneDebugger::initialize() { +Array SceneDebugger::RPCProfilerFrame::serialize() { + Array arr; + arr.push_back(infos.size() * 4); + for (int i = 0; i < infos.size(); ++i) { + arr.push_back(uint64_t(infos[i].node)); + arr.push_back(infos[i].node_path); + arr.push_back(infos[i].incoming_rpc); + arr.push_back(infos[i].outgoing_rpc); + } + return arr; +} + +bool SceneDebugger::RPCProfilerFrame::deserialize(const Array &p_arr) { + ERR_FAIL_COND_V(p_arr.size() < 1, false); + uint32_t size = p_arr[0]; + ERR_FAIL_COND_V(size % 4, false); + ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false); + infos.resize(size / 4); + int idx = 1; + for (uint32_t i = 0; i < size / 4; ++i) { + infos.write[i].node = uint64_t(p_arr[idx]); + infos.write[i].node_path = p_arr[idx + 1]; + infos.write[i].incoming_rpc = p_arr[idx + 2]; + infos.write[i].outgoing_rpc = p_arr[idx + 3]; + } + return true; +} + +class SceneDebugger::RPCProfiler : public EngineProfiler { + Map rpc_node_data; + uint64_t last_profile_time = 0; + + void init_node(const ObjectID p_node) { + if (rpc_node_data.has(p_node)) { + return; + } + rpc_node_data.insert(p_node, RPCNodeInfo()); + rpc_node_data[p_node].node = p_node; + rpc_node_data[p_node].node_path = Object::cast_to(ObjectDB::get_instance(p_node))->get_path(); + rpc_node_data[p_node].incoming_rpc = 0; + rpc_node_data[p_node].outgoing_rpc = 0; + } + +public: + void toggle(bool p_enable, const Array &p_opts) { + rpc_node_data.clear(); + } + + void add(const Array &p_data) { + ERR_FAIL_COND(p_data.size() < 2); + const ObjectID id = p_data[0]; + const String what = p_data[1]; + init_node(id); + RPCNodeInfo &info = rpc_node_data[id]; + if (what == "rpc_in") { + info.incoming_rpc++; + } else if (what == "rpc_out") { + info.outgoing_rpc++; + } + } + + void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) { + uint64_t pt = OS::get_singleton()->get_ticks_msec(); + if (pt - last_profile_time > 100) { + last_profile_time = pt; + RPCProfilerFrame frame; + for (const KeyValue &E : rpc_node_data) { + frame.infos.push_back(E.value); + } + rpc_node_data.clear(); + EngineDebugger::get_singleton()->send_message("multiplayer:rpc", frame.serialize()); + } + } +}; + +SceneDebugger *SceneDebugger::singleton = nullptr; + +SceneDebugger::SceneDebugger() { + singleton = this; + rpc_profiler.instantiate(); + rpc_profiler->bind("rpc"); #ifdef DEBUG_ENABLED LiveEditor::singleton = memnew(LiveEditor); EngineDebugger::register_message_capture("scene", EngineDebugger::Capture(nullptr, SceneDebugger::parse_message)); #endif } -void SceneDebugger::deinitialize() { +SceneDebugger::~SceneDebugger() { #ifdef DEBUG_ENABLED if (LiveEditor::singleton) { - // Should be removed automatically when deiniting debugger, but just in case - if (EngineDebugger::has_capture("scene")) { - EngineDebugger::unregister_message_capture("scene"); - } + EngineDebugger::unregister_message_capture("scene"); memdelete(LiveEditor::singleton); LiveEditor::singleton = nullptr; } #endif + singleton = nullptr; +} + +void SceneDebugger::initialize() { + if (EngineDebugger::is_active()) { + memnew(SceneDebugger); + } +} + +void SceneDebugger::deinitialize() { + if (singleton) { + memdelete(singleton); + } } #ifdef DEBUG_ENABLED diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index c8298391bb..dd0a17c2dc 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -32,6 +32,7 @@ #define SCENE_DEBUGGER_H #include "core/object/class_db.h" +#include "core/object/ref_counted.h" #include "core/string/ustring.h" #include "core/templates/pair.h" #include "core/variant/array.h" @@ -40,10 +41,37 @@ class Script; class Node; class SceneDebugger { +public: + // RPC profiler + struct RPCNodeInfo { + ObjectID node; + String node_path; + int incoming_rpc = 0; + int outgoing_rpc = 0; + }; + + struct RPCProfilerFrame { + Vector infos; + + Array serialize(); + bool deserialize(const Array &p_arr); + }; + +private: + class RPCProfiler; + + static SceneDebugger *singleton; + + Ref rpc_profiler; + + SceneDebugger(); + public: static void initialize(); static void deinitialize(); + ~SceneDebugger(); + #ifdef DEBUG_ENABLED private: static void _save_node(ObjectID id, const String &p_path); -- cgit v1.2.3