Merge pull request #68758 from Faless/mp/4.x_better_debug
[MP] Improve network profiler.
This commit is contained in:
commit
1bc131afb8
10 changed files with 72 additions and 61 deletions
|
@ -67,8 +67,8 @@ void EditorNetworkProfiler::_update_frame() {
|
|||
}
|
||||
|
||||
node->set_text(0, E.value.node_path);
|
||||
node->set_text(1, E.value.incoming_rpc == 0 ? "-" : itos(E.value.incoming_rpc));
|
||||
node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : itos(E.value.outgoing_rpc));
|
||||
node->set_text(1, E.value.incoming_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.incoming_rpc, String::humanize_size(E.value.incoming_size)));
|
||||
node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.outgoing_rpc, String::humanize_size(E.value.outgoing_size)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,12 @@ void EditorNetworkProfiler::add_node_frame_data(const RPCNodeInfo p_frame) {
|
|||
nodes_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc;
|
||||
nodes_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc;
|
||||
}
|
||||
if (p_frame.incoming_rpc) {
|
||||
nodes_data[p_frame.node].incoming_size = p_frame.incoming_size / p_frame.incoming_rpc;
|
||||
}
|
||||
if (p_frame.outgoing_rpc) {
|
||||
nodes_data[p_frame.node].outgoing_size = p_frame.outgoing_size / p_frame.outgoing_rpc;
|
||||
}
|
||||
|
||||
if (frame_delay->is_stopped()) {
|
||||
frame_delay->set_wait_time(0.1);
|
||||
|
|
|
@ -66,7 +66,7 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void add_node_frame_data(const RPCNodeInfo p_frame);
|
||||
void add_node_frame_data(RPCNodeInfo p_frame);
|
||||
void set_bandwidth(int p_incoming, int p_outgoing);
|
||||
bool is_profiling();
|
||||
|
||||
|
|
|
@ -126,12 +126,14 @@ void MultiplayerDebugger::BandwidthProfiler::tick(double p_frame_time, double p_
|
|||
|
||||
Array MultiplayerDebugger::RPCFrame::serialize() {
|
||||
Array arr;
|
||||
arr.push_back(infos.size() * 4);
|
||||
arr.push_back(infos.size() * 6);
|
||||
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].incoming_size);
|
||||
arr.push_back(infos[i].outgoing_rpc);
|
||||
arr.push_back(infos[i].outgoing_size);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
@ -139,15 +141,18 @@ Array MultiplayerDebugger::RPCFrame::serialize() {
|
|||
bool MultiplayerDebugger::RPCFrame::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(size % 6, false);
|
||||
ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
|
||||
infos.resize(size / 4);
|
||||
infos.resize(size / 6);
|
||||
int idx = 1;
|
||||
for (uint32_t i = 0; i < size / 4; ++i) {
|
||||
for (uint32_t i = 0; i < size / 6; 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];
|
||||
infos.write[i].incoming_size = p_arr[idx + 3];
|
||||
infos.write[i].outgoing_rpc = p_arr[idx + 4];
|
||||
infos.write[i].outgoing_size = p_arr[idx + 5];
|
||||
idx += 6;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -159,8 +164,6 @@ void MultiplayerDebugger::RPCProfiler::init_node(const ObjectID p_node) {
|
|||
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<Node>(ObjectDB::get_instance(p_node))->get_path();
|
||||
rpc_node_data[p_node].incoming_rpc = 0;
|
||||
rpc_node_data[p_node].outgoing_rpc = 0;
|
||||
}
|
||||
|
||||
void MultiplayerDebugger::RPCProfiler::toggle(bool p_enable, const Array &p_opts) {
|
||||
|
@ -168,15 +171,18 @@ void MultiplayerDebugger::RPCProfiler::toggle(bool p_enable, const Array &p_opts
|
|||
}
|
||||
|
||||
void MultiplayerDebugger::RPCProfiler::add(const Array &p_data) {
|
||||
ERR_FAIL_COND(p_data.size() < 2);
|
||||
const ObjectID id = p_data[0];
|
||||
const String what = p_data[1];
|
||||
ERR_FAIL_COND(p_data.size() != 3);
|
||||
const String what = p_data[0];
|
||||
const ObjectID id = p_data[1];
|
||||
const int size = p_data[2];
|
||||
init_node(id);
|
||||
RPCNodeInfo &info = rpc_node_data[id];
|
||||
if (what == "rpc_in") {
|
||||
info.incoming_rpc++;
|
||||
info.incoming_size += size;
|
||||
} else if (what == "rpc_out") {
|
||||
info.outgoing_rpc++;
|
||||
info.outgoing_size += size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@ public:
|
|||
ObjectID node;
|
||||
String node_path;
|
||||
int incoming_rpc = 0;
|
||||
int incoming_size = 0;
|
||||
int outgoing_rpc = 0;
|
||||
int outgoing_size = 0;
|
||||
};
|
||||
|
||||
struct RPCFrame {
|
||||
|
|
|
@ -99,10 +99,6 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
|
|||
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
|
||||
ERR_FAIL_COND(multiplayer_peer.is_null());
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
multiplayer->profile_bandwidth("out", packet.size());
|
||||
#endif
|
||||
|
||||
multiplayer_peer->set_transfer_channel(0);
|
||||
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
|
||||
multiplayer->send_command(p_from, packet.ptr(), packet.size());
|
||||
|
@ -155,10 +151,6 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
|
|||
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
|
||||
ERR_FAIL_COND_V(multiplayer_peer.is_null(), ERR_BUG);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
multiplayer->profile_bandwidth("out", packet.size() * p_peers.size());
|
||||
#endif
|
||||
|
||||
Error err = OK;
|
||||
for (int peer_id : p_peers) {
|
||||
multiplayer_peer->set_transfer_channel(0);
|
||||
|
|
|
@ -40,12 +40,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) {
|
||||
_FORCE_INLINE_ void SceneMultiplayer::_profile_bandwidth(const String &p_what, int p_value) {
|
||||
if (EngineDebugger::is_profiling("multiplayer")) {
|
||||
Array values;
|
||||
values.push_back(p_inout);
|
||||
values.push_back(p_what);
|
||||
values.push_back(OS::get_singleton()->get_ticks_msec());
|
||||
values.push_back(p_size);
|
||||
values.push_back(p_value);
|
||||
EngineDebugger::profiler_add_frame_data("multiplayer", values);
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,10 @@ Error SceneMultiplayer::poll() {
|
|||
Error err = multiplayer_peer->get_packet(&packet, len);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_profile_bandwidth("in", len);
|
||||
#endif
|
||||
|
||||
if (pending_peers.has(sender)) {
|
||||
if (pending_peers[sender].local) {
|
||||
// If the auth is over, admit the peer at the first packet.
|
||||
|
@ -220,10 +224,6 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
|
|||
ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via SceneMultiplayer.set_root_path before using it.");
|
||||
ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
profile_bandwidth("in", p_packet_len);
|
||||
#endif
|
||||
|
||||
// Extract the `packet_type` from the LSB three bits:
|
||||
uint8_t packet_type = p_packet[0] & CMD_MASK;
|
||||
|
||||
|
@ -258,6 +258,13 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ Error SceneMultiplayer::_send(const uint8_t *p_packet, int p_packet_len) {
|
||||
_profile_bandwidth("out", p_packet_len);
|
||||
return multiplayer_peer->put_packet(p_packet, p_packet_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_packet_len) {
|
||||
if (server_relay && get_unique_id() != 1 && p_to != 1 && multiplayer_peer->is_server_relay_supported()) {
|
||||
// Send relay packet.
|
||||
|
@ -268,19 +275,19 @@ Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_pa
|
|||
relay_buffer->put_data(p_packet, p_packet_len);
|
||||
multiplayer_peer->set_target_peer(1);
|
||||
const Vector<uint8_t> data = relay_buffer->get_data_array();
|
||||
return multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
|
||||
return _send(data.ptr(), relay_buffer->get_position());
|
||||
}
|
||||
if (p_to > 0) {
|
||||
ERR_FAIL_COND_V(!connected_peers.has(p_to), ERR_BUG);
|
||||
multiplayer_peer->set_target_peer(p_to);
|
||||
return multiplayer_peer->put_packet(p_packet, p_packet_len);
|
||||
return _send(p_packet, p_packet_len);
|
||||
} else {
|
||||
for (const int &pid : connected_peers) {
|
||||
if (p_to && pid == -p_to) {
|
||||
continue;
|
||||
}
|
||||
multiplayer_peer->set_target_peer(pid);
|
||||
multiplayer_peer->put_packet(p_packet, p_packet_len);
|
||||
_send(p_packet, p_packet_len);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
@ -319,7 +326,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
|
|||
multiplayer_peer->set_transfer_channel(p_channel);
|
||||
if (peer > 0) {
|
||||
multiplayer_peer->set_target_peer(peer);
|
||||
multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
|
||||
_send(data.ptr(), relay_buffer->get_position());
|
||||
} else {
|
||||
for (const int &P : connected_peers) {
|
||||
// Not to sender, nor excluded.
|
||||
|
@ -327,7 +334,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
|
|||
continue;
|
||||
}
|
||||
multiplayer_peer->set_target_peer(P);
|
||||
multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
|
||||
_send(data.ptr(), relay_buffer->get_position());
|
||||
}
|
||||
}
|
||||
if (peer == 0 || peer == -1) {
|
||||
|
@ -373,11 +380,11 @@ void SceneMultiplayer::_admit_peer(int p_id) {
|
|||
// Send new peer to already connected.
|
||||
encode_uint32(p_id, &buf[2]);
|
||||
multiplayer_peer->set_target_peer(P);
|
||||
multiplayer_peer->put_packet(buf, sizeof(buf));
|
||||
_send(buf, sizeof(buf));
|
||||
// Send already connected to new peer.
|
||||
encode_uint32(P, &buf[2]);
|
||||
multiplayer_peer->set_target_peer(p_id);
|
||||
multiplayer_peer->put_packet(buf, sizeof(buf));
|
||||
_send(buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +419,7 @@ void SceneMultiplayer::_del_peer(int p_id) {
|
|||
continue;
|
||||
}
|
||||
multiplayer_peer->set_target_peer(P);
|
||||
multiplayer_peer->put_packet(buf, sizeof(buf));
|
||||
_send(buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,7 +475,7 @@ Error SceneMultiplayer::send_auth(int p_to, Vector<uint8_t> p_data) {
|
|||
multiplayer_peer->set_target_peer(p_to);
|
||||
multiplayer_peer->set_transfer_channel(0);
|
||||
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
|
||||
return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 2);
|
||||
return _send(packet_cache.ptr(), p_data.size() + 2);
|
||||
}
|
||||
|
||||
Error SceneMultiplayer::complete_auth(int p_peer) {
|
||||
|
@ -478,7 +485,7 @@ Error SceneMultiplayer::complete_auth(int p_peer) {
|
|||
pending_peers[p_peer].local = true;
|
||||
// Notify the remote peer that the authentication has completed.
|
||||
uint8_t buf[2] = { NETWORK_COMMAND_SYS, SYS_COMMAND_AUTH };
|
||||
Error err = multiplayer_peer->put_packet(buf, 2);
|
||||
Error err = _send(buf, 2);
|
||||
// The remote peer already reported the authentication as completed, so admit the peer.
|
||||
// May generate new packets, so it must happen after sending confirmation.
|
||||
if (pending_peers[p_peer].remote) {
|
||||
|
|
|
@ -103,6 +103,15 @@ private:
|
|||
Ref<SceneReplicationInterface> replicator;
|
||||
Ref<SceneRPCInterface> rpc;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void _profile_bandwidth(const String &p_what, int p_value);
|
||||
_FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len); // Also profiles.
|
||||
#else
|
||||
_FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len) {
|
||||
return multiplayer_peer->put_packet(p_packet, p_packet_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -163,10 +172,6 @@ public:
|
|||
|
||||
Ref<SceneCacheInterface> get_path_cache() { return cache; }
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void profile_bandwidth(const String &p_inout, int p_size);
|
||||
#endif
|
||||
|
||||
SceneMultiplayer();
|
||||
~SceneMultiplayer();
|
||||
};
|
||||
|
|
|
@ -362,13 +362,8 @@ Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const Obje
|
|||
|
||||
Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable) {
|
||||
ERR_FAIL_COND_V(!p_buffer || p_size < 1, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(!multiplayer, ERR_UNCONFIGURED);
|
||||
ERR_FAIL_COND_V(!multiplayer->has_multiplayer_peer(), ERR_UNCONFIGURED);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
multiplayer->profile_bandwidth("out", p_size);
|
||||
#endif
|
||||
|
||||
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
|
||||
peer->set_transfer_channel(0);
|
||||
peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
|
||||
|
|
|
@ -52,16 +52,15 @@
|
|||
#define BYTE_ONLY_OR_NO_ARGS_FLAG (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT)
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {
|
||||
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
|
||||
if (EngineDebugger::is_profiling("rpc")) {
|
||||
Array values;
|
||||
values.push_back(p_id);
|
||||
values.push_back(p_what);
|
||||
values.push_back(p_id);
|
||||
values.push_back(p_size);
|
||||
EngineDebugger::profiler_add_frame_data("rpc", values);
|
||||
}
|
||||
}
|
||||
#else
|
||||
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {}
|
||||
#endif
|
||||
|
||||
// Returns the packet size stripping the node path added when the node is not yet cached.
|
||||
|
@ -277,7 +276,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
|
|||
argp.resize(argc);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_profile_node_data("rpc_in", p_node->get_instance_id());
|
||||
_profile_node_data("rpc_in", p_node->get_instance_id(), p_packet_len);
|
||||
#endif
|
||||
|
||||
int out;
|
||||
|
@ -399,13 +398,13 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
|
|||
ERR_FAIL_COND(node_id_compression > 3);
|
||||
ERR_FAIL_COND(name_id_compression > 1);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_profile_node_data("rpc_out", p_from->get_instance_id(), ofs);
|
||||
#endif
|
||||
|
||||
// We can now set the meta
|
||||
packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + (byte_only_or_no_args ? BYTE_ONLY_OR_NO_ARGS_FLAG : 0);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
multiplayer->profile_bandwidth("out", ofs);
|
||||
#endif
|
||||
|
||||
// Take chance and set transfer mode, since all send methods will use it.
|
||||
peer->set_transfer_channel(p_config.channel);
|
||||
peer->set_transfer_mode(p_config.transfer_mode);
|
||||
|
@ -477,10 +476,6 @@ Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_
|
|||
}
|
||||
|
||||
if (p_peer_id != caller_id) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
_profile_node_data("rpc_out", node->get_instance_id());
|
||||
#endif
|
||||
|
||||
_send_rpc(node, p_peer_id, rpc_id, config, p_method, p_arg, p_argcount);
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,11 @@ private:
|
|||
|
||||
HashMap<ObjectID, RPCConfigCache> rpc_cache;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
_FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id);
|
||||
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
|
||||
|
||||
void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
|
||||
|
|
Loading…
Reference in a new issue